alepha 0.13.1 → 0.13.2

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 (296) hide show
  1. package/README.md +1 -1
  2. package/dist/api-files/index.d.ts +28 -91
  3. package/dist/api-files/index.js +10 -755
  4. package/dist/api-files/index.js.map +1 -1
  5. package/dist/api-jobs/index.d.ts +46 -46
  6. package/dist/api-jobs/index.js +13 -13
  7. package/dist/api-jobs/index.js.map +1 -1
  8. package/dist/api-notifications/index.d.ts +129 -146
  9. package/dist/api-notifications/index.js +17 -39
  10. package/dist/api-notifications/index.js.map +1 -1
  11. package/dist/api-parameters/index.d.ts +21 -22
  12. package/dist/api-parameters/index.js +22 -22
  13. package/dist/api-parameters/index.js.map +1 -1
  14. package/dist/api-users/index.d.ts +223 -2000
  15. package/dist/api-users/index.js +914 -4787
  16. package/dist/api-users/index.js.map +1 -1
  17. package/dist/api-verifications/index.d.ts +96 -96
  18. package/dist/batch/index.d.ts +13 -13
  19. package/dist/batch/index.js +8 -8
  20. package/dist/batch/index.js.map +1 -1
  21. package/dist/bucket/index.d.ts +14 -14
  22. package/dist/bucket/index.js +12 -12
  23. package/dist/bucket/index.js.map +1 -1
  24. package/dist/cache/index.d.ts +11 -11
  25. package/dist/cache/index.js +9 -9
  26. package/dist/cache/index.js.map +1 -1
  27. package/dist/cli/index.d.ts +28 -26
  28. package/dist/cli/index.js +50 -13
  29. package/dist/cli/index.js.map +1 -1
  30. package/dist/command/index.d.ts +19 -19
  31. package/dist/command/index.js +25 -25
  32. package/dist/command/index.js.map +1 -1
  33. package/dist/core/index.browser.js +218 -218
  34. package/dist/core/index.browser.js.map +1 -1
  35. package/dist/core/index.d.ts +232 -232
  36. package/dist/core/index.js +218 -218
  37. package/dist/core/index.js.map +1 -1
  38. package/dist/core/index.native.js +2113 -0
  39. package/dist/core/index.native.js.map +1 -0
  40. package/dist/datetime/index.d.ts +9 -9
  41. package/dist/datetime/index.js +7 -7
  42. package/dist/datetime/index.js.map +1 -1
  43. package/dist/email/index.d.ts +16 -16
  44. package/dist/email/index.js +9 -9
  45. package/dist/email/index.js.map +1 -1
  46. package/dist/file/index.js +1 -1
  47. package/dist/file/index.js.map +1 -1
  48. package/dist/lock/index.d.ts +9 -9
  49. package/dist/lock/index.js +8 -8
  50. package/dist/lock/index.js.map +1 -1
  51. package/dist/lock-redis/index.js +3 -66
  52. package/dist/lock-redis/index.js.map +1 -1
  53. package/dist/logger/index.d.ts +5 -5
  54. package/dist/logger/index.js +8 -8
  55. package/dist/logger/index.js.map +1 -1
  56. package/dist/orm/index.browser.js +114 -114
  57. package/dist/orm/index.browser.js.map +1 -1
  58. package/dist/orm/index.d.ts +218 -218
  59. package/dist/orm/index.js +46 -46
  60. package/dist/orm/index.js.map +1 -1
  61. package/dist/queue/index.d.ts +29 -29
  62. package/dist/queue/index.js +20 -20
  63. package/dist/queue/index.js.map +1 -1
  64. package/dist/queue-redis/index.d.ts +2 -2
  65. package/dist/redis/index.d.ts +10 -10
  66. package/dist/retry/index.d.ts +19 -19
  67. package/dist/retry/index.js +7 -7
  68. package/dist/retry/index.js.map +1 -1
  69. package/dist/scheduler/index.d.ts +16 -16
  70. package/dist/scheduler/index.js +9 -9
  71. package/dist/scheduler/index.js.map +1 -1
  72. package/dist/security/index.d.ts +80 -80
  73. package/dist/security/index.js +32 -32
  74. package/dist/security/index.js.map +1 -1
  75. package/dist/server/index.browser.js +1 -1
  76. package/dist/server/index.browser.js.map +1 -1
  77. package/dist/server/index.d.ts +101 -101
  78. package/dist/server/index.js +16 -16
  79. package/dist/server/index.js.map +1 -1
  80. package/dist/server-auth/index.browser.js +4 -982
  81. package/dist/server-auth/index.browser.js.map +1 -1
  82. package/dist/server-auth/index.d.ts +204 -785
  83. package/dist/server-auth/index.js +47 -1239
  84. package/dist/server-auth/index.js.map +1 -1
  85. package/dist/server-cache/index.d.ts +10 -10
  86. package/dist/server-cache/index.js +2 -2
  87. package/dist/server-cache/index.js.map +1 -1
  88. package/dist/server-compress/index.d.ts +4 -4
  89. package/dist/server-compress/index.js +1 -1
  90. package/dist/server-compress/index.js.map +1 -1
  91. package/dist/server-cookies/index.browser.js +8 -8
  92. package/dist/server-cookies/index.browser.js.map +1 -1
  93. package/dist/server-cookies/index.d.ts +17 -17
  94. package/dist/server-cookies/index.js +10 -10
  95. package/dist/server-cookies/index.js.map +1 -1
  96. package/dist/server-cors/index.d.ts +17 -17
  97. package/dist/server-cors/index.js +9 -9
  98. package/dist/server-cors/index.js.map +1 -1
  99. package/dist/server-health/index.d.ts +19 -19
  100. package/dist/server-helmet/index.d.ts +1 -1
  101. package/dist/server-links/index.browser.js +12 -12
  102. package/dist/server-links/index.browser.js.map +1 -1
  103. package/dist/server-links/index.d.ts +59 -251
  104. package/dist/server-links/index.js +23 -502
  105. package/dist/server-links/index.js.map +1 -1
  106. package/dist/server-metrics/index.d.ts +4 -4
  107. package/dist/server-multipart/index.d.ts +2 -2
  108. package/dist/server-proxy/index.d.ts +12 -12
  109. package/dist/server-proxy/index.js +10 -10
  110. package/dist/server-proxy/index.js.map +1 -1
  111. package/dist/server-rate-limit/index.d.ts +22 -22
  112. package/dist/server-rate-limit/index.js +12 -12
  113. package/dist/server-rate-limit/index.js.map +1 -1
  114. package/dist/server-security/index.d.ts +22 -22
  115. package/dist/server-security/index.js +15 -15
  116. package/dist/server-security/index.js.map +1 -1
  117. package/dist/server-static/index.d.ts +14 -14
  118. package/dist/server-static/index.js +8 -8
  119. package/dist/server-static/index.js.map +1 -1
  120. package/dist/server-swagger/index.d.ts +25 -184
  121. package/dist/server-swagger/index.js +21 -724
  122. package/dist/server-swagger/index.js.map +1 -1
  123. package/dist/sms/index.d.ts +14 -14
  124. package/dist/sms/index.js +9 -9
  125. package/dist/sms/index.js.map +1 -1
  126. package/dist/thread/index.d.ts +11 -11
  127. package/dist/thread/index.js +17 -17
  128. package/dist/thread/index.js.map +1 -1
  129. package/dist/topic/index.d.ts +26 -26
  130. package/dist/topic/index.js +16 -16
  131. package/dist/topic/index.js.map +1 -1
  132. package/dist/topic-redis/index.d.ts +1 -1
  133. package/dist/vite/index.d.ts +3 -3
  134. package/dist/vite/index.js +8 -8
  135. package/dist/vite/index.js.map +1 -1
  136. package/dist/websocket/index.browser.js +11 -11
  137. package/dist/websocket/index.browser.js.map +1 -1
  138. package/dist/websocket/index.d.ts +58 -58
  139. package/dist/websocket/index.js +13 -13
  140. package/dist/websocket/index.js.map +1 -1
  141. package/package.json +113 -52
  142. package/src/api-files/services/FileService.ts +5 -7
  143. package/src/api-jobs/index.ts +1 -1
  144. package/src/api-jobs/{descriptors → primitives}/$job.ts +8 -8
  145. package/src/api-jobs/providers/JobProvider.ts +9 -9
  146. package/src/api-jobs/services/JobService.ts +5 -5
  147. package/src/api-notifications/index.ts +5 -15
  148. package/src/api-notifications/{descriptors → primitives}/$notification.ts +10 -10
  149. package/src/api-notifications/services/NotificationSenderService.ts +3 -3
  150. package/src/api-parameters/index.ts +1 -1
  151. package/src/api-parameters/{descriptors → primitives}/$config.ts +7 -12
  152. package/src/api-users/index.ts +1 -1
  153. package/src/api-users/{descriptors → primitives}/$userRealm.ts +8 -8
  154. package/src/api-users/providers/UserRealmProvider.ts +1 -1
  155. package/src/batch/index.ts +3 -3
  156. package/src/batch/{descriptors → primitives}/$batch.ts +13 -16
  157. package/src/bucket/index.ts +8 -8
  158. package/src/bucket/{descriptors → primitives}/$bucket.ts +8 -8
  159. package/src/bucket/providers/LocalFileStorageProvider.ts +3 -3
  160. package/src/cache/index.ts +4 -4
  161. package/src/cache/{descriptors → primitives}/$cache.ts +15 -15
  162. package/src/cli/apps/AlephaPackageBuilderCli.ts +24 -2
  163. package/src/cli/commands/DrizzleCommands.ts +6 -6
  164. package/src/cli/commands/VerifyCommands.ts +1 -1
  165. package/src/cli/commands/ViteCommands.ts +6 -1
  166. package/src/cli/services/ProjectUtils.ts +34 -3
  167. package/src/command/index.ts +5 -5
  168. package/src/command/{descriptors → primitives}/$command.ts +9 -12
  169. package/src/command/providers/CliProvider.ts +10 -10
  170. package/src/core/Alepha.ts +30 -33
  171. package/src/core/constants/KIND.ts +1 -1
  172. package/src/core/constants/OPTIONS.ts +1 -1
  173. package/src/core/helpers/{descriptor.ts → primitive.ts} +18 -18
  174. package/src/core/helpers/ref.ts +1 -1
  175. package/src/core/index.shared.ts +8 -8
  176. package/src/core/{descriptors → primitives}/$context.ts +5 -5
  177. package/src/core/{descriptors → primitives}/$hook.ts +4 -4
  178. package/src/core/{descriptors → primitives}/$inject.ts +2 -2
  179. package/src/core/{descriptors → primitives}/$module.ts +9 -9
  180. package/src/core/{descriptors → primitives}/$use.ts +2 -2
  181. package/src/core/providers/CodecManager.ts +1 -1
  182. package/src/core/providers/JsonSchemaCodec.ts +1 -1
  183. package/src/core/providers/StateManager.ts +2 -2
  184. package/src/datetime/index.ts +3 -3
  185. package/src/datetime/{descriptors → primitives}/$interval.ts +6 -6
  186. package/src/email/index.ts +4 -4
  187. package/src/email/{descriptors → primitives}/$email.ts +8 -8
  188. package/src/file/index.ts +1 -1
  189. package/src/lock/index.ts +3 -3
  190. package/src/lock/{descriptors → primitives}/$lock.ts +10 -10
  191. package/src/logger/index.ts +8 -8
  192. package/src/logger/{descriptors → primitives}/$logger.ts +2 -2
  193. package/src/logger/services/Logger.ts +1 -1
  194. package/src/orm/constants/PG_SYMBOLS.ts +2 -2
  195. package/src/orm/index.browser.ts +2 -2
  196. package/src/orm/index.ts +8 -8
  197. package/src/orm/{descriptors → primitives}/$entity.ts +11 -11
  198. package/src/orm/{descriptors → primitives}/$repository.ts +2 -2
  199. package/src/orm/{descriptors → primitives}/$sequence.ts +8 -8
  200. package/src/orm/{descriptors → primitives}/$transaction.ts +4 -4
  201. package/src/orm/providers/PostgresTypeProvider.ts +3 -3
  202. package/src/orm/providers/RepositoryProvider.ts +4 -4
  203. package/src/orm/providers/drivers/DatabaseProvider.ts +7 -7
  204. package/src/orm/services/ModelBuilder.ts +9 -9
  205. package/src/orm/services/PgRelationManager.ts +2 -2
  206. package/src/orm/services/PostgresModelBuilder.ts +5 -5
  207. package/src/orm/services/Repository.ts +7 -7
  208. package/src/orm/services/SqliteModelBuilder.ts +5 -5
  209. package/src/queue/index.ts +7 -7
  210. package/src/queue/{descriptors → primitives}/$consumer.ts +15 -15
  211. package/src/queue/{descriptors → primitives}/$queue.ts +12 -12
  212. package/src/queue/providers/WorkerProvider.ts +7 -7
  213. package/src/retry/index.ts +3 -3
  214. package/src/retry/{descriptors → primitives}/$retry.ts +14 -14
  215. package/src/scheduler/index.ts +3 -3
  216. package/src/scheduler/{descriptors → primitives}/$scheduler.ts +9 -9
  217. package/src/scheduler/providers/CronProvider.ts +1 -1
  218. package/src/security/index.ts +9 -9
  219. package/src/security/{descriptors → primitives}/$permission.ts +7 -7
  220. package/src/security/{descriptors → primitives}/$realm.ts +6 -12
  221. package/src/security/{descriptors → primitives}/$role.ts +12 -12
  222. package/src/security/{descriptors → primitives}/$serviceAccount.ts +8 -8
  223. package/src/server/index.browser.ts +1 -1
  224. package/src/server/index.ts +14 -14
  225. package/src/server/{descriptors → primitives}/$action.ts +13 -13
  226. package/src/server/{descriptors → primitives}/$route.ts +9 -9
  227. package/src/server/providers/NodeHttpServerProvider.ts +1 -1
  228. package/src/server/services/HttpClient.ts +1 -1
  229. package/src/server-auth/index.browser.ts +1 -1
  230. package/src/server-auth/index.ts +6 -6
  231. package/src/server-auth/{descriptors → primitives}/$auth.ts +10 -10
  232. package/src/server-auth/{descriptors → primitives}/$authCredentials.ts +4 -4
  233. package/src/server-auth/{descriptors → primitives}/$authGithub.ts +4 -4
  234. package/src/server-auth/{descriptors → primitives}/$authGoogle.ts +4 -4
  235. package/src/server-auth/providers/ServerAuthProvider.ts +4 -4
  236. package/src/server-cache/providers/ServerCacheProvider.ts +7 -7
  237. package/src/server-compress/providers/ServerCompressProvider.ts +3 -3
  238. package/src/server-cookies/index.browser.ts +2 -2
  239. package/src/server-cookies/index.ts +5 -5
  240. package/src/server-cookies/{descriptors → primitives}/$cookie.browser.ts +12 -12
  241. package/src/server-cookies/{descriptors → primitives}/$cookie.ts +13 -13
  242. package/src/server-cookies/providers/ServerCookiesProvider.ts +4 -4
  243. package/src/server-cookies/services/CookieParser.ts +1 -1
  244. package/src/server-cors/index.ts +3 -3
  245. package/src/server-cors/{descriptors → primitives}/$cors.ts +11 -13
  246. package/src/server-cors/providers/ServerCorsProvider.ts +5 -5
  247. package/src/server-links/index.browser.ts +5 -5
  248. package/src/server-links/index.ts +9 -9
  249. package/src/server-links/{descriptors → primitives}/$remote.ts +11 -11
  250. package/src/server-links/providers/LinkProvider.ts +7 -7
  251. package/src/server-links/providers/{RemoteDescriptorProvider.ts → RemotePrimitiveProvider.ts} +6 -6
  252. package/src/server-links/providers/ServerLinksProvider.ts +3 -3
  253. package/src/server-proxy/index.ts +3 -3
  254. package/src/server-proxy/{descriptors → primitives}/$proxy.ts +8 -8
  255. package/src/server-proxy/providers/ServerProxyProvider.ts +4 -4
  256. package/src/server-rate-limit/index.ts +6 -6
  257. package/src/server-rate-limit/{descriptors → primitives}/$rateLimit.ts +13 -13
  258. package/src/server-rate-limit/providers/ServerRateLimitProvider.ts +5 -5
  259. package/src/server-security/index.ts +3 -3
  260. package/src/server-security/{descriptors → primitives}/$basicAuth.ts +13 -13
  261. package/src/server-security/providers/ServerBasicAuthProvider.ts +5 -5
  262. package/src/server-security/providers/ServerSecurityProvider.ts +4 -4
  263. package/src/server-static/index.ts +3 -3
  264. package/src/server-static/{descriptors → primitives}/$serve.ts +8 -10
  265. package/src/server-static/providers/ServerStaticProvider.ts +6 -6
  266. package/src/server-swagger/index.ts +5 -5
  267. package/src/server-swagger/{descriptors → primitives}/$swagger.ts +9 -9
  268. package/src/server-swagger/providers/ServerSwaggerProvider.ts +11 -10
  269. package/src/sms/index.ts +4 -4
  270. package/src/sms/{descriptors → primitives}/$sms.ts +8 -8
  271. package/src/thread/index.ts +3 -3
  272. package/src/thread/{descriptors → primitives}/$thread.ts +13 -13
  273. package/src/thread/providers/ThreadProvider.ts +7 -9
  274. package/src/topic/index.ts +5 -5
  275. package/src/topic/{descriptors → primitives}/$subscriber.ts +14 -14
  276. package/src/topic/{descriptors → primitives}/$topic.ts +10 -10
  277. package/src/topic/providers/TopicProvider.ts +4 -4
  278. package/src/vite/tasks/copyAssets.ts +1 -1
  279. package/src/vite/tasks/generateSitemap.ts +3 -3
  280. package/src/vite/tasks/prerenderPages.ts +2 -2
  281. package/src/vite/tasks/runAlepha.ts +2 -2
  282. package/src/websocket/index.browser.ts +3 -3
  283. package/src/websocket/index.shared.ts +2 -2
  284. package/src/websocket/index.ts +4 -4
  285. package/src/websocket/interfaces/WebSocketInterfaces.ts +3 -3
  286. package/src/websocket/{descriptors → primitives}/$channel.ts +10 -10
  287. package/src/websocket/{descriptors → primitives}/$websocket.ts +8 -8
  288. package/src/websocket/providers/NodeWebSocketServerProvider.ts +7 -7
  289. package/src/websocket/providers/WebSocketServerProvider.ts +3 -3
  290. package/src/websocket/services/WebSocketClient.ts +5 -5
  291. package/src/api-notifications/providers/MemorySmsProvider.ts +0 -20
  292. package/src/api-notifications/providers/SmsProvider.ts +0 -8
  293. /package/src/core/{descriptors → primitives}/$atom.ts +0 -0
  294. /package/src/core/{descriptors → primitives}/$env.ts +0 -0
  295. /package/src/server-auth/{descriptors → primitives}/$authApple.ts +0 -0
  296. /package/src/server-links/{descriptors → primitives}/$client.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["cookies: Record<string, string>","headers","parts: string[]","envSchema","cookie: Cookie","USER_AGENT","ERR_INVALID_ARG_VALUE","ERR_INVALID_ARG_TYPE","CodedTypeError","allowInsecureRequests","clockSkew","clockTolerance","customFetch","modifyAssertion","decoder","headers","signal","performDiscovery","assertString","randomBytes","calculatePKCECodeChallenge","ClientSecretPost","None","skipSubjectCheck","skipStateCheck","oauth.ClientSecretPost","headers","oauth.None","oauth.skipStateCheck","oauth.skipSubjectCheck","oauth.customFetch","oauth.modifyAssertion","oauth.clockSkew","oauth.clockTolerance","oauth.calculatePKCECodeChallenge","oauth.generateRandomCodeVerifier","oauth.generateRandomState","oauth.ResponseBodyError","oauth.AuthorizationResponseError","oauth.WWWAuthenticateChallengeError","oauth.OperationProcessingError","oauth.HTTP_REQUEST_FORBIDDEN","oauth.REQUEST_PROTOCOL_FORBIDDEN","oauth.RESPONSE_IS_NOT_CONFORM","oauth.RESPONSE_IS_NOT_JSON","oauth.PARSE_ERROR","oauth.INVALID_RESPONSE","oauth.JWT_CLAIM_COMPARISON","oauth.JSON_ATTRIBUTE_COMPARISON","oauth.JWT_TIMESTAMP_CHECK","oauth.UnsupportedOperationError","oauth.UNSUPPORTED_OPERATION","signal","oauth.discoveryRequest","oauth.allowInsecureRequests","oauth.processDiscoveryResponse","oauth._nodiscoverycheck","oauth._expectedIssuer","oauth.getValidatedIdTokenClaims","oauth.formPostResponse","oauth.validateAuthResponse","oauth\n .authorizationCodeGrantRequest","oauth.nopkce","fetch","oauth.processAuthorizationCodeResponse","oauth.jweDecrypt","oauth\n .refreshTokenGrantRequest","oauth.processRefreshTokenResponse","oauth.resolveEndpoint","oauth.isDPoPNonceError","addons: Array<(config: Configuration) => void>","user: UserAccountToken | undefined","ownership: boolean | string | undefined","$: VirtualAction<T>","WebStream","envSchema","remote: ServerRemote","name","url","headers","permissions: Permission[] | undefined","permissionMap: Map<string, Permission> | undefined","userLinks: ApiLink[]","providers: AuthenticationProvider[]","e","user","headers","user: UserAccount | undefined","parameters: Record<string, string>","parameters","tokens","identity","account: CredentialsFn | undefined","account: LinkAccountFn | undefined","res","user: OAuth2Profile","emails: any[]","e","account: LinkAccountFn | undefined"],"sources":["../../src/server-cookies/services/CookieParser.ts","../../src/server-cookies/providers/ServerCookiesProvider.ts","../../src/server-cookies/descriptors/$cookie.ts","../../src/server-cookies/index.ts","../../../../node_modules/oauth4webapi/build/index.js","../../../../node_modules/openid-client/build/index.js","../../src/server-auth/descriptors/$auth.ts","../../src/server-security/providers/ServerBasicAuthProvider.ts","../../src/server-security/descriptors/$basicAuth.ts","../../src/server-security/providers/ServerSecurityProvider.ts","../../src/server-security/index.ts","../../src/server-links/schemas/apiLinksResponseSchema.ts","../../src/server-links/providers/LinkProvider.ts","../../src/server-links/descriptors/$client.ts","../../src/server-links/descriptors/$remote.ts","../../src/server-proxy/descriptors/$proxy.ts","../../src/server-proxy/providers/ServerProxyProvider.ts","../../src/server-proxy/index.ts","../../src/server-links/providers/RemoteDescriptorProvider.ts","../../src/server-links/providers/ServerLinksProvider.ts","../../src/server-links/index.ts","../../src/server-auth/constants/routes.ts","../../src/server-auth/schemas/tokensSchema.ts","../../src/server-auth/schemas/tokenResponseSchema.ts","../../src/server-auth/schemas/userinfoResponseSchema.ts","../../src/server-auth/providers/ServerAuthProvider.ts","../../src/server-auth/descriptors/$authCredentials.ts","../../src/server-auth/descriptors/$authGithub.ts","../../src/server-auth/descriptors/$authGoogle.ts","../../src/server-auth/schemas/authenticationProviderSchema.ts","../../src/server-auth/index.ts"],"sourcesContent":["import type { Cookie } from \"../descriptors/$cookie.ts\";\n\nexport class CookieParser {\n public parseRequestCookies(header: string): Record<string, string> {\n const cookies: Record<string, string> = {};\n const parts = header.split(\";\");\n for (const part of parts) {\n const [key, value] = part.split(\"=\");\n if (!key || !value) {\n continue;\n }\n\n cookies[key.trim()] = value.trim();\n }\n\n return cookies;\n }\n\n public serializeResponseCookies(\n cookies: Record<string, Cookie | null>,\n isHttps: boolean,\n ): string[] {\n const headers = [];\n\n for (const [name, cookie] of Object.entries(cookies)) {\n // If the cookie is null, we need to delete it\n if (cookie == null) {\n headers.push(`${name}=; Path=/; Max-Age=0`);\n continue;\n }\n\n if (!cookie.value) {\n continue;\n }\n\n headers.push(this.cookieToString(name, cookie, isHttps));\n }\n\n return headers;\n }\n\n public cookieToString(\n name: string,\n cookie: Cookie,\n isHttps?: boolean,\n ): string {\n const parts: string[] = [];\n\n parts.push(`${name}=${cookie.value}`);\n\n if (cookie.path) {\n parts.push(`Path=${cookie.path}`);\n }\n if (cookie.maxAge) {\n parts.push(`Max-Age=${cookie.maxAge}`);\n }\n if (cookie.secure !== false && isHttps) {\n parts.push(\"Secure\");\n }\n if (cookie.httpOnly) {\n parts.push(\"HttpOnly\");\n }\n if (cookie.sameSite) {\n parts.push(`SameSite=${cookie.sameSite}`);\n }\n if (cookie.domain) {\n parts.push(`Domain=${cookie.domain}`);\n }\n\n return parts.join(\"; \");\n }\n}\n","import {\n createCipheriv,\n createDecipheriv,\n createHmac,\n randomBytes,\n timingSafeEqual,\n} from \"node:crypto\";\nimport { deflateRawSync, inflateRawSync } from \"node:zlib\";\nimport {\n $env,\n $hook,\n $inject,\n Alepha,\n type Static,\n type TSchema,\n t,\n} from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { DEFAULT_APP_SECRET } from \"alepha/security\";\nimport type { ServerRequest } from \"alepha/server\";\nimport type {\n Cookie,\n CookieDescriptorOptions,\n Cookies,\n} from \"../descriptors/$cookie.ts\";\nimport { CookieParser } from \"../services/CookieParser.ts\";\n\nconst envSchema = t.object({\n APP_SECRET: t.text({\n default: DEFAULT_APP_SECRET,\n }),\n});\n\nexport class ServerCookiesProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n protected readonly cookieParser = $inject(CookieParser);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly env = $env(envSchema);\n\n // crypto constants\n protected readonly ALGORITHM = \"aes-256-gcm\";\n protected readonly IV_LENGTH = 16; // For GCM\n protected readonly AUTH_TAG_LENGTH = 16;\n protected readonly SIGNATURE_LENGTH = 32; // For SHA256\n\n public readonly onRequest = $hook({\n on: \"server:onRequest\",\n handler: async ({ request }) => {\n request.cookies = {\n req: this.cookieParser.parseRequestCookies(\n request.headers.cookie ?? \"\",\n ),\n res: {},\n };\n },\n });\n\n public readonly onAction = $hook({\n on: \"action:onRequest\",\n handler: async ({ request }) => {\n request.cookies = {\n req: this.cookieParser.parseRequestCookies(\n request.headers.cookie ?? \"\",\n ),\n res: {},\n };\n },\n });\n\n public readonly onSend = $hook({\n on: \"server:onSend\",\n handler: async ({ request }) => {\n if (request.cookies && Object.keys(request.cookies.res).length > 0) {\n const setCookieHeaders = this.cookieParser.serializeResponseCookies(\n request.cookies.res,\n request.url.protocol === \"https:\",\n );\n if (setCookieHeaders.length > 0) {\n request.reply.headers[\"set-cookie\"] = setCookieHeaders;\n }\n }\n },\n });\n\n protected getCookiesFromContext(cookies?: Cookies): Cookies {\n const contextCookies =\n this.alepha.context.get<ServerRequest>(\"request\")?.cookies;\n if (cookies) return cookies;\n if (contextCookies) return contextCookies;\n throw new Error(\n \"Cookie context is not available. This method must be called within a server request cycle.\",\n );\n }\n\n public getCookie<T extends TSchema>(\n name: string,\n options: CookieDescriptorOptions<T>,\n contextCookies?: Cookies,\n ): Static<T> | undefined {\n const cookies = this.getCookiesFromContext(contextCookies);\n let rawValue = cookies.req[name];\n\n if (!rawValue) return undefined;\n\n try {\n rawValue = decodeURIComponent(rawValue);\n\n if (options.sign) {\n const signature = rawValue.substring(0, this.SIGNATURE_LENGTH * 2);\n const value = rawValue.substring(this.SIGNATURE_LENGTH * 2);\n const expectedSignature = this.sign(value);\n\n if (\n !timingSafeEqual(\n Buffer.from(signature, \"hex\"),\n Buffer.from(expectedSignature, \"hex\"),\n )\n ) {\n this.log.warn(`Invalid signature for cookie \"${name}\".`);\n return undefined;\n }\n rawValue = value;\n }\n\n if (options.encrypt) {\n rawValue = this.decrypt(rawValue);\n }\n\n if (options.compress) {\n rawValue = inflateRawSync(Buffer.from(rawValue, \"base64\")).toString(\n \"utf8\",\n );\n }\n\n return this.alepha.codec.decode(options.schema, JSON.parse(rawValue));\n } catch (error) {\n this.log.warn(`Failed to parse cookie \"${name}\"`, error);\n // corrupted or invalid cookie, instruct browser to delete it on next response\n this.deleteCookie(name, cookies);\n return undefined;\n }\n }\n\n public setCookie<T extends TSchema>(\n name: string,\n options: CookieDescriptorOptions<T>,\n data: Static<T>,\n contextCookies?: Cookies,\n ): void {\n const cookies = this.getCookiesFromContext(contextCookies);\n let value = JSON.stringify(this.alepha.codec.decode(options.schema, data));\n\n if (options.compress) {\n value = deflateRawSync(value).toString(\"base64\");\n }\n\n if (options.encrypt) {\n value = this.encrypt(value);\n }\n\n if (options.sign) {\n value = this.sign(value) + value;\n }\n\n const cookie: Cookie = {\n value: encodeURIComponent(value),\n path: options.path ?? \"/\",\n sameSite: options.sameSite ?? \"lax\",\n secure: options.secure ?? this.alepha.isProduction(),\n httpOnly: options.httpOnly,\n domain: options.domain,\n };\n\n if (options.ttl) {\n cookie.maxAge = this.dateTimeProvider.duration(options.ttl).as(\"seconds\");\n }\n\n cookies.res[name] = cookie;\n }\n\n public deleteCookie<T extends TSchema>(\n name: string,\n contextCookies?: Cookies,\n ): void {\n const cookies = this.getCookiesFromContext(contextCookies);\n cookies.res[name] = null;\n }\n\n // --- Crypto & Parsing ---\n\n protected encrypt(text: string): string {\n const iv = randomBytes(this.IV_LENGTH);\n const cipher = createCipheriv(\n this.ALGORITHM,\n Buffer.from(this.secretKey()),\n iv,\n );\n const encrypted = Buffer.concat([\n cipher.update(text, \"utf8\"),\n cipher.final(),\n ]);\n const authTag = cipher.getAuthTag();\n return Buffer.concat([iv, authTag, encrypted]).toString(\"base64\");\n }\n\n protected decrypt(encryptedText: string): string {\n const data = Buffer.from(encryptedText, \"base64\");\n const iv = data.subarray(0, this.IV_LENGTH);\n const authTag = data.subarray(\n this.IV_LENGTH,\n this.IV_LENGTH + this.AUTH_TAG_LENGTH,\n );\n\n const encrypted = data.subarray(this.IV_LENGTH + this.AUTH_TAG_LENGTH);\n const decipher = createDecipheriv(\n this.ALGORITHM,\n Buffer.from(this.secretKey()),\n iv,\n );\n\n decipher.setAuthTag(authTag);\n\n const decrypted = Buffer.concat([\n decipher.update(encrypted),\n decipher.final(),\n ]);\n\n return decrypted.toString(\"utf8\");\n }\n\n public secretKey(): string {\n let secret = this.env.APP_SECRET;\n if (secret.length < 32) {\n // pad secret to 32 bytes\n secret = secret.padEnd(32, \"0\");\n } else if (secret.length > 32) {\n // truncate secret to 32 bytes\n secret = secret.substring(0, 32);\n }\n return secret;\n }\n\n protected sign(data: string): string {\n return createHmac(\"sha256\", this.secretKey()).update(data).digest(\"hex\");\n }\n}\n","import {\n $inject,\n createDescriptor,\n Descriptor,\n KIND,\n type Static,\n type TSchema,\n} from \"alepha\";\nimport type { DurationLike } from \"alepha/datetime\";\nimport { ServerCookiesProvider } from \"../providers/ServerCookiesProvider.ts\";\n\n/**\n * Declares a type-safe, configurable HTTP cookie.\n * This descriptor provides methods to get, set, and delete the cookie\n * within the server request/response cycle.\n */\nexport const $cookie = <T extends TSchema>(\n options: CookieDescriptorOptions<T>,\n): AbstractCookieDescriptor<T> => {\n return createDescriptor(CookieDescriptor<T>, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface CookieDescriptorOptions<T extends TSchema> {\n /** The schema for the cookie's value, used for validation and type safety. */\n schema: T;\n\n /** The name of the cookie. */\n name?: string;\n\n /** The cookie's path. Defaults to \"/\". */\n path?: string;\n\n /** Time-to-live for the cookie. Maps to `Max-Age`. */\n ttl?: DurationLike;\n\n /** If true, the cookie is only sent over HTTPS. Defaults to true in production. */\n secure?: boolean;\n\n /** If true, the cookie cannot be accessed by client-side scripts. */\n httpOnly?: boolean;\n\n /** SameSite policy for the cookie. Defaults to \"lax\". */\n sameSite?: \"strict\" | \"lax\" | \"none\";\n\n /** The domain for the cookie. */\n domain?: string;\n\n /** If true, the cookie value will be compressed using zlib. */\n compress?: boolean;\n\n /** If true, the cookie value will be encrypted. Requires `COOKIE_SECRET` env var. */\n encrypt?: boolean;\n\n /** If true, the cookie will be signed to prevent tampering. Requires `COOKIE_SECRET` env var. */\n sign?: boolean;\n}\n\nexport interface AbstractCookieDescriptor<T extends TSchema> {\n readonly name: string;\n readonly options: CookieDescriptorOptions<T>;\n set(\n value: Static<T>,\n options?: { cookies?: Cookies; ttl?: DurationLike },\n ): void;\n get(options?: { cookies?: Cookies }): Static<T> | undefined;\n del(options?: { cookies?: Cookies }): void;\n}\n\nexport class CookieDescriptor<T extends TSchema>\n extends Descriptor<CookieDescriptorOptions<T>>\n implements AbstractCookieDescriptor<T>\n{\n protected readonly serverCookiesProvider = $inject(ServerCookiesProvider);\n\n public get schema(): T {\n return this.options.schema;\n }\n\n public get name(): string {\n return this.options.name ?? `${this.config.propertyKey}`;\n }\n\n /**\n * Sets the cookie with the given value in the current request's response.\n */\n public set(\n value: Static<T>,\n options?: { cookies?: Cookies; ttl?: DurationLike },\n ): void {\n this.serverCookiesProvider.setCookie(\n this.name,\n {\n ...this.options,\n ttl: options?.ttl ?? this.options.ttl,\n },\n value,\n options?.cookies,\n );\n }\n\n /**\n * Gets the cookie value from the current request. Returns undefined if not found or invalid.\n */\n public get(options?: { cookies?: Cookies }): Static<T> | undefined {\n return this.serverCookiesProvider.getCookie(\n this.name,\n this.options,\n options?.cookies,\n );\n }\n\n /**\n * Deletes the cookie in the current request's response.\n */\n public del(options?: { cookies?: Cookies }): void {\n this.serverCookiesProvider.deleteCookie(this.name, options?.cookies);\n }\n}\n\n$cookie[KIND] = CookieDescriptor;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface Cookies {\n req: Record<string, string>;\n res: Record<string, Cookie | null>;\n}\n\nexport interface Cookie {\n value: string;\n path?: string;\n maxAge?: number;\n secure?: boolean;\n httpOnly?: boolean;\n sameSite?: \"strict\" | \"lax\" | \"none\";\n domain?: string;\n}\n","import { $module } from \"alepha\";\nimport { AlephaServer } from \"alepha/server\";\nimport { $cookie, type Cookies } from \"./descriptors/$cookie.ts\";\nimport { ServerCookiesProvider } from \"./providers/ServerCookiesProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./descriptors/$cookie.ts\";\nexport * from \"./providers/ServerCookiesProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha/server\" {\n interface ServerRequest {\n cookies: Cookies;\n }\n}\n\n/**\n * Provides HTTP cookie management capabilities for server requests and responses with type-safe cookie descriptors.\n *\n * The server-cookies module enables declarative cookie handling using the `$cookie` descriptor on class properties.\n * It offers automatic cookie parsing, secure cookie configuration, and seamless integration with server routes\n * for managing user sessions, preferences, and authentication tokens.\n *\n * @see {@link $cookie}\n * @module alepha.server.cookies\n */\nexport const AlephaServerCookies = $module({\n name: \"alepha.server.cookies\",\n descriptors: [$cookie],\n services: [AlephaServer, ServerCookiesProvider],\n});\n","let USER_AGENT;\nif (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {\n const NAME = 'oauth4webapi';\n const VERSION = 'v3.8.2';\n USER_AGENT = `${NAME}/${VERSION}`;\n}\nfunction looseInstanceOf(input, expected) {\n if (input == null) {\n return false;\n }\n try {\n return (input instanceof expected ||\n Object.getPrototypeOf(input)[Symbol.toStringTag] === expected.prototype[Symbol.toStringTag]);\n }\n catch {\n return false;\n }\n}\nconst ERR_INVALID_ARG_VALUE = 'ERR_INVALID_ARG_VALUE';\nconst ERR_INVALID_ARG_TYPE = 'ERR_INVALID_ARG_TYPE';\nfunction CodedTypeError(message, code, cause) {\n const err = new TypeError(message, { cause });\n Object.assign(err, { code });\n return err;\n}\nexport const allowInsecureRequests = Symbol();\nexport const clockSkew = Symbol();\nexport const clockTolerance = Symbol();\nexport const customFetch = Symbol();\nexport const modifyAssertion = Symbol();\nexport const jweDecrypt = Symbol();\nexport const jwksCache = Symbol();\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\nfunction buf(input) {\n if (typeof input === 'string') {\n return encoder.encode(input);\n }\n return decoder.decode(input);\n}\nlet encodeBase64Url;\nif (Uint8Array.prototype.toBase64) {\n encodeBase64Url = (input) => {\n if (input instanceof ArrayBuffer) {\n input = new Uint8Array(input);\n }\n return input.toBase64({ alphabet: 'base64url', omitPadding: true });\n };\n}\nelse {\n const CHUNK_SIZE = 0x8000;\n encodeBase64Url = (input) => {\n if (input instanceof ArrayBuffer) {\n input = new Uint8Array(input);\n }\n const arr = [];\n for (let i = 0; i < input.byteLength; i += CHUNK_SIZE) {\n arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));\n }\n return btoa(arr.join('')).replace(/=/g, '').replace(/\\+/g, '-').replace(/\\//g, '_');\n };\n}\nlet decodeBase64Url;\nif (Uint8Array.fromBase64) {\n decodeBase64Url = (input) => {\n try {\n return Uint8Array.fromBase64(input, { alphabet: 'base64url' });\n }\n catch (cause) {\n throw CodedTypeError('The input to be decoded is not correctly encoded.', ERR_INVALID_ARG_VALUE, cause);\n }\n };\n}\nelse {\n decodeBase64Url = (input) => {\n try {\n const binary = atob(input.replace(/-/g, '+').replace(/_/g, '/').replace(/\\s/g, ''));\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n }\n catch (cause) {\n throw CodedTypeError('The input to be decoded is not correctly encoded.', ERR_INVALID_ARG_VALUE, cause);\n }\n };\n}\nfunction b64u(input) {\n if (typeof input === 'string') {\n return decodeBase64Url(input);\n }\n return encodeBase64Url(input);\n}\nexport class UnsupportedOperationError extends Error {\n code;\n constructor(message, options) {\n super(message, options);\n this.name = this.constructor.name;\n this.code = UNSUPPORTED_OPERATION;\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nexport class OperationProcessingError extends Error {\n code;\n constructor(message, options) {\n super(message, options);\n this.name = this.constructor.name;\n if (options?.code) {\n this.code = options?.code;\n }\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nfunction OPE(message, code, cause) {\n return new OperationProcessingError(message, { code, cause });\n}\nasync function calculateJwkThumbprint(jwk) {\n let components;\n switch (jwk.kty) {\n case 'EC':\n components = {\n crv: jwk.crv,\n kty: jwk.kty,\n x: jwk.x,\n y: jwk.y,\n };\n break;\n case 'OKP':\n components = {\n crv: jwk.crv,\n kty: jwk.kty,\n x: jwk.x,\n };\n break;\n case 'AKP':\n components = {\n alg: jwk.alg,\n kty: jwk.kty,\n pub: jwk.pub,\n };\n break;\n case 'RSA':\n components = {\n e: jwk.e,\n kty: jwk.kty,\n n: jwk.n,\n };\n break;\n default:\n throw new UnsupportedOperationError('unsupported JWK key type', { cause: jwk });\n }\n return b64u(await crypto.subtle.digest('SHA-256', buf(JSON.stringify(components))));\n}\nfunction assertCryptoKey(key, it) {\n if (!(key instanceof CryptoKey)) {\n throw CodedTypeError(`${it} must be a CryptoKey`, ERR_INVALID_ARG_TYPE);\n }\n}\nfunction assertPrivateKey(key, it) {\n assertCryptoKey(key, it);\n if (key.type !== 'private') {\n throw CodedTypeError(`${it} must be a private CryptoKey`, ERR_INVALID_ARG_VALUE);\n }\n}\nfunction assertPublicKey(key, it) {\n assertCryptoKey(key, it);\n if (key.type !== 'public') {\n throw CodedTypeError(`${it} must be a public CryptoKey`, ERR_INVALID_ARG_VALUE);\n }\n}\nfunction normalizeTyp(value) {\n return value.toLowerCase().replace(/^application\\//, '');\n}\nfunction isJsonObject(input) {\n if (input === null || typeof input !== 'object' || Array.isArray(input)) {\n return false;\n }\n return true;\n}\nfunction prepareHeaders(input) {\n if (looseInstanceOf(input, Headers)) {\n input = Object.fromEntries(input.entries());\n }\n const headers = new Headers(input ?? {});\n if (USER_AGENT && !headers.has('user-agent')) {\n headers.set('user-agent', USER_AGENT);\n }\n if (headers.has('authorization')) {\n throw CodedTypeError('\"options.headers\" must not include the \"authorization\" header name', ERR_INVALID_ARG_VALUE);\n }\n return headers;\n}\nfunction signal(url, value) {\n if (value !== undefined) {\n if (typeof value === 'function') {\n value = value(url.href);\n }\n if (!(value instanceof AbortSignal)) {\n throw CodedTypeError('\"options.signal\" must return or be an instance of AbortSignal', ERR_INVALID_ARG_TYPE);\n }\n return value;\n }\n return undefined;\n}\nfunction replaceDoubleSlash(pathname) {\n if (pathname.includes('//')) {\n return pathname.replace('//', '/');\n }\n return pathname;\n}\nfunction prependWellKnown(url, wellKnown, allowTerminatingSlash = false) {\n if (url.pathname === '/') {\n url.pathname = wellKnown;\n }\n else {\n url.pathname = replaceDoubleSlash(`${wellKnown}/${allowTerminatingSlash ? url.pathname : url.pathname.replace(/(\\/)$/, '')}`);\n }\n return url;\n}\nfunction appendWellKnown(url, wellKnown) {\n url.pathname = replaceDoubleSlash(`${url.pathname}/${wellKnown}`);\n return url;\n}\nasync function performDiscovery(input, urlName, transform, options) {\n if (!(input instanceof URL)) {\n throw CodedTypeError(`\"${urlName}\" must be an instance of URL`, ERR_INVALID_ARG_TYPE);\n }\n checkProtocol(input, options?.[allowInsecureRequests] !== true);\n const url = transform(new URL(input.href));\n const headers = prepareHeaders(options?.headers);\n headers.set('accept', 'application/json');\n return (options?.[customFetch] || fetch)(url.href, {\n body: undefined,\n headers: Object.fromEntries(headers.entries()),\n method: 'GET',\n redirect: 'manual',\n signal: signal(url, options?.signal),\n });\n}\nexport async function discoveryRequest(issuerIdentifier, options) {\n return performDiscovery(issuerIdentifier, 'issuerIdentifier', (url) => {\n switch (options?.algorithm) {\n case undefined:\n case 'oidc':\n appendWellKnown(url, '.well-known/openid-configuration');\n break;\n case 'oauth2':\n prependWellKnown(url, '.well-known/oauth-authorization-server');\n break;\n default:\n throw CodedTypeError('\"options.algorithm\" must be \"oidc\" (default), or \"oauth2\"', ERR_INVALID_ARG_VALUE);\n }\n return url;\n }, options);\n}\nfunction assertNumber(input, allow0, it, code, cause) {\n try {\n if (typeof input !== 'number' || !Number.isFinite(input)) {\n throw CodedTypeError(`${it} must be a number`, ERR_INVALID_ARG_TYPE, cause);\n }\n if (input > 0)\n return;\n if (allow0) {\n if (input !== 0) {\n throw CodedTypeError(`${it} must be a non-negative number`, ERR_INVALID_ARG_VALUE, cause);\n }\n return;\n }\n throw CodedTypeError(`${it} must be a positive number`, ERR_INVALID_ARG_VALUE, cause);\n }\n catch (err) {\n if (code) {\n throw OPE(err.message, code, cause);\n }\n throw err;\n }\n}\nfunction assertString(input, it, code, cause) {\n try {\n if (typeof input !== 'string') {\n throw CodedTypeError(`${it} must be a string`, ERR_INVALID_ARG_TYPE, cause);\n }\n if (input.length === 0) {\n throw CodedTypeError(`${it} must not be empty`, ERR_INVALID_ARG_VALUE, cause);\n }\n }\n catch (err) {\n if (code) {\n throw OPE(err.message, code, cause);\n }\n throw err;\n }\n}\nexport async function processDiscoveryResponse(expectedIssuerIdentifier, response) {\n const expected = expectedIssuerIdentifier;\n if (!(expected instanceof URL) && expected !== _nodiscoverycheck) {\n throw CodedTypeError('\"expectedIssuerIdentifier\" must be an instance of URL', ERR_INVALID_ARG_TYPE);\n }\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n if (response.status !== 200) {\n throw OPE('\"response\" is not a conform Authorization Server Metadata response (unexpected HTTP status code)', RESPONSE_IS_NOT_CONFORM, response);\n }\n assertReadableResponse(response);\n const json = await getResponseJsonBody(response);\n assertString(json.issuer, '\"response\" body \"issuer\" property', INVALID_RESPONSE, { body: json });\n if (expected !== _nodiscoverycheck && new URL(json.issuer).href !== expected.href) {\n throw OPE('\"response\" body \"issuer\" property does not match the expected value', JSON_ATTRIBUTE_COMPARISON, { expected: expected.href, body: json, attribute: 'issuer' });\n }\n return json;\n}\nfunction assertApplicationJson(response) {\n assertContentType(response, 'application/json');\n}\nfunction notJson(response, ...types) {\n let msg = '\"response\" content-type must be ';\n if (types.length > 2) {\n const last = types.pop();\n msg += `${types.join(', ')}, or ${last}`;\n }\n else if (types.length === 2) {\n msg += `${types[0]} or ${types[1]}`;\n }\n else {\n msg += types[0];\n }\n return OPE(msg, RESPONSE_IS_NOT_JSON, response);\n}\nfunction assertContentTypes(response, ...types) {\n if (!types.includes(getContentType(response))) {\n throw notJson(response, ...types);\n }\n}\nfunction assertContentType(response, contentType) {\n if (getContentType(response) !== contentType) {\n throw notJson(response, contentType);\n }\n}\nfunction randomBytes() {\n return b64u(crypto.getRandomValues(new Uint8Array(32)));\n}\nexport function generateRandomCodeVerifier() {\n return randomBytes();\n}\nexport function generateRandomState() {\n return randomBytes();\n}\nexport function generateRandomNonce() {\n return randomBytes();\n}\nexport async function calculatePKCECodeChallenge(codeVerifier) {\n assertString(codeVerifier, 'codeVerifier');\n return b64u(await crypto.subtle.digest('SHA-256', buf(codeVerifier)));\n}\nfunction getKeyAndKid(input) {\n if (input instanceof CryptoKey) {\n return { key: input };\n }\n if (!(input?.key instanceof CryptoKey)) {\n return {};\n }\n if (input.kid !== undefined) {\n assertString(input.kid, '\"kid\"');\n }\n return {\n key: input.key,\n kid: input.kid,\n };\n}\nfunction psAlg(key) {\n switch (key.algorithm.hash.name) {\n case 'SHA-256':\n return 'PS256';\n case 'SHA-384':\n return 'PS384';\n case 'SHA-512':\n return 'PS512';\n default:\n throw new UnsupportedOperationError('unsupported RsaHashedKeyAlgorithm hash name', {\n cause: key,\n });\n }\n}\nfunction rsAlg(key) {\n switch (key.algorithm.hash.name) {\n case 'SHA-256':\n return 'RS256';\n case 'SHA-384':\n return 'RS384';\n case 'SHA-512':\n return 'RS512';\n default:\n throw new UnsupportedOperationError('unsupported RsaHashedKeyAlgorithm hash name', {\n cause: key,\n });\n }\n}\nfunction esAlg(key) {\n switch (key.algorithm.namedCurve) {\n case 'P-256':\n return 'ES256';\n case 'P-384':\n return 'ES384';\n case 'P-521':\n return 'ES512';\n default:\n throw new UnsupportedOperationError('unsupported EcKeyAlgorithm namedCurve', { cause: key });\n }\n}\nfunction keyToJws(key) {\n switch (key.algorithm.name) {\n case 'RSA-PSS':\n return psAlg(key);\n case 'RSASSA-PKCS1-v1_5':\n return rsAlg(key);\n case 'ECDSA':\n return esAlg(key);\n case 'Ed25519':\n case 'ML-DSA-44':\n case 'ML-DSA-65':\n case 'ML-DSA-87':\n return key.algorithm.name;\n case 'EdDSA':\n return 'Ed25519';\n default:\n throw new UnsupportedOperationError('unsupported CryptoKey algorithm name', { cause: key });\n }\n}\nfunction getClockSkew(client) {\n const skew = client?.[clockSkew];\n return typeof skew === 'number' && Number.isFinite(skew) ? skew : 0;\n}\nfunction getClockTolerance(client) {\n const tolerance = client?.[clockTolerance];\n return typeof tolerance === 'number' && Number.isFinite(tolerance) && Math.sign(tolerance) !== -1\n ? tolerance\n : 30;\n}\nfunction epochTime() {\n return Math.floor(Date.now() / 1000);\n}\nfunction assertAs(as) {\n if (typeof as !== 'object' || as === null) {\n throw CodedTypeError('\"as\" must be an object', ERR_INVALID_ARG_TYPE);\n }\n assertString(as.issuer, '\"as.issuer\"');\n}\nfunction assertClient(client) {\n if (typeof client !== 'object' || client === null) {\n throw CodedTypeError('\"client\" must be an object', ERR_INVALID_ARG_TYPE);\n }\n assertString(client.client_id, '\"client.client_id\"');\n}\nfunction formUrlEncode(token) {\n return encodeURIComponent(token).replace(/(?:[-_.!~*'()]|%20)/g, (substring) => {\n switch (substring) {\n case '-':\n case '_':\n case '.':\n case '!':\n case '~':\n case '*':\n case \"'\":\n case '(':\n case ')':\n return `%${substring.charCodeAt(0).toString(16).toUpperCase()}`;\n case '%20':\n return '+';\n default:\n throw new Error();\n }\n });\n}\nexport function ClientSecretPost(clientSecret) {\n assertString(clientSecret, '\"clientSecret\"');\n return (_as, client, body, _headers) => {\n body.set('client_id', client.client_id);\n body.set('client_secret', clientSecret);\n };\n}\nexport function ClientSecretBasic(clientSecret) {\n assertString(clientSecret, '\"clientSecret\"');\n return (_as, client, _body, headers) => {\n const username = formUrlEncode(client.client_id);\n const password = formUrlEncode(clientSecret);\n const credentials = btoa(`${username}:${password}`);\n headers.set('authorization', `Basic ${credentials}`);\n };\n}\nfunction clientAssertionPayload(as, client) {\n const now = epochTime() + getClockSkew(client);\n return {\n jti: randomBytes(),\n aud: as.issuer,\n exp: now + 60,\n iat: now,\n nbf: now,\n iss: client.client_id,\n sub: client.client_id,\n };\n}\nexport function PrivateKeyJwt(clientPrivateKey, options) {\n const { key, kid } = getKeyAndKid(clientPrivateKey);\n assertPrivateKey(key, '\"clientPrivateKey.key\"');\n return async (as, client, body, _headers) => {\n const header = { alg: keyToJws(key), kid };\n const payload = clientAssertionPayload(as, client);\n options?.[modifyAssertion]?.(header, payload);\n body.set('client_id', client.client_id);\n body.set('client_assertion_type', 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer');\n body.set('client_assertion', await signJwt(header, payload, key));\n };\n}\nexport function ClientSecretJwt(clientSecret, options) {\n assertString(clientSecret, '\"clientSecret\"');\n const modify = options?.[modifyAssertion];\n let key;\n return async (as, client, body, _headers) => {\n key ||= await crypto.subtle.importKey('raw', buf(clientSecret), { hash: 'SHA-256', name: 'HMAC' }, false, ['sign']);\n const header = { alg: 'HS256' };\n const payload = clientAssertionPayload(as, client);\n modify?.(header, payload);\n const data = `${b64u(buf(JSON.stringify(header)))}.${b64u(buf(JSON.stringify(payload)))}`;\n const hmac = await crypto.subtle.sign(key.algorithm, key, buf(data));\n body.set('client_id', client.client_id);\n body.set('client_assertion_type', 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer');\n body.set('client_assertion', `${data}.${b64u(new Uint8Array(hmac))}`);\n };\n}\nexport function None() {\n return (_as, client, body, _headers) => {\n body.set('client_id', client.client_id);\n };\n}\nexport function TlsClientAuth() {\n return None();\n}\nasync function signJwt(header, payload, key) {\n if (!key.usages.includes('sign')) {\n throw CodedTypeError('CryptoKey instances used for signing assertions must include \"sign\" in their \"usages\"', ERR_INVALID_ARG_VALUE);\n }\n const input = `${b64u(buf(JSON.stringify(header)))}.${b64u(buf(JSON.stringify(payload)))}`;\n const signature = b64u(await crypto.subtle.sign(keyToSubtle(key), key, buf(input)));\n return `${input}.${signature}`;\n}\nexport async function issueRequestObject(as, client, parameters, privateKey, options) {\n assertAs(as);\n assertClient(client);\n parameters = new URLSearchParams(parameters);\n const { key, kid } = getKeyAndKid(privateKey);\n assertPrivateKey(key, '\"privateKey.key\"');\n parameters.set('client_id', client.client_id);\n const now = epochTime() + getClockSkew(client);\n const claims = {\n ...Object.fromEntries(parameters.entries()),\n jti: randomBytes(),\n aud: as.issuer,\n exp: now + 60,\n iat: now,\n nbf: now,\n iss: client.client_id,\n };\n let resource;\n if (parameters.has('resource') &&\n (resource = parameters.getAll('resource')) &&\n resource.length > 1) {\n claims.resource = resource;\n }\n {\n let value = parameters.get('max_age');\n if (value !== null) {\n claims.max_age = parseInt(value, 10);\n assertNumber(claims.max_age, true, '\"max_age\" parameter');\n }\n }\n {\n let value = parameters.get('claims');\n if (value !== null) {\n try {\n claims.claims = JSON.parse(value);\n }\n catch (cause) {\n throw OPE('failed to parse the \"claims\" parameter as JSON', PARSE_ERROR, cause);\n }\n if (!isJsonObject(claims.claims)) {\n throw CodedTypeError('\"claims\" parameter must be a JSON with a top level object', ERR_INVALID_ARG_VALUE);\n }\n }\n }\n {\n let value = parameters.get('authorization_details');\n if (value !== null) {\n try {\n claims.authorization_details = JSON.parse(value);\n }\n catch (cause) {\n throw OPE('failed to parse the \"authorization_details\" parameter as JSON', PARSE_ERROR, cause);\n }\n if (!Array.isArray(claims.authorization_details)) {\n throw CodedTypeError('\"authorization_details\" parameter must be a JSON with a top level array', ERR_INVALID_ARG_VALUE);\n }\n }\n }\n const header = {\n alg: keyToJws(key),\n typ: 'oauth-authz-req+jwt',\n kid,\n };\n options?.[modifyAssertion]?.(header, claims);\n return signJwt(header, claims, key);\n}\nlet jwkCache;\nasync function getSetPublicJwkCache(key, alg) {\n const { kty, e, n, x, y, crv, pub } = await crypto.subtle.exportKey('jwk', key);\n const jwk = { kty, e, n, x, y, crv, pub };\n if (kty === 'AKP')\n jwk.alg = alg;\n jwkCache.set(key, jwk);\n return jwk;\n}\nasync function publicJwk(key, alg) {\n jwkCache ||= new WeakMap();\n return jwkCache.get(key) || getSetPublicJwkCache(key, alg);\n}\nconst URLParse = URL.parse\n ?\n (url, base) => URL.parse(url, base)\n : (url, base) => {\n try {\n return new URL(url, base);\n }\n catch {\n return null;\n }\n };\nexport function checkProtocol(url, enforceHttps) {\n if (enforceHttps && url.protocol !== 'https:') {\n throw OPE('only requests to HTTPS are allowed', HTTP_REQUEST_FORBIDDEN, url);\n }\n if (url.protocol !== 'https:' && url.protocol !== 'http:') {\n throw OPE('only HTTP and HTTPS requests are allowed', REQUEST_PROTOCOL_FORBIDDEN, url);\n }\n}\nfunction validateEndpoint(value, endpoint, useMtlsAlias, enforceHttps) {\n let url;\n if (typeof value !== 'string' || !(url = URLParse(value))) {\n throw OPE(`authorization server metadata does not contain a valid ${useMtlsAlias ? `\"as.mtls_endpoint_aliases.${endpoint}\"` : `\"as.${endpoint}\"`}`, value === undefined ? MISSING_SERVER_METADATA : INVALID_SERVER_METADATA, { attribute: useMtlsAlias ? `mtls_endpoint_aliases.${endpoint}` : endpoint });\n }\n checkProtocol(url, enforceHttps);\n return url;\n}\nexport function resolveEndpoint(as, endpoint, useMtlsAlias, enforceHttps) {\n if (useMtlsAlias && as.mtls_endpoint_aliases && endpoint in as.mtls_endpoint_aliases) {\n return validateEndpoint(as.mtls_endpoint_aliases[endpoint], endpoint, useMtlsAlias, enforceHttps);\n }\n return validateEndpoint(as[endpoint], endpoint, useMtlsAlias, enforceHttps);\n}\nexport async function pushedAuthorizationRequest(as, client, clientAuthentication, parameters, options) {\n assertAs(as);\n assertClient(client);\n const url = resolveEndpoint(as, 'pushed_authorization_request_endpoint', client.use_mtls_endpoint_aliases, options?.[allowInsecureRequests] !== true);\n const body = new URLSearchParams(parameters);\n body.set('client_id', client.client_id);\n const headers = prepareHeaders(options?.headers);\n headers.set('accept', 'application/json');\n if (options?.DPoP !== undefined) {\n assertDPoP(options.DPoP);\n await options.DPoP.addProof(url, headers, 'POST');\n }\n const response = await authenticatedRequest(as, client, clientAuthentication, url, body, headers, options);\n options?.DPoP?.cacheNonce(response, url);\n return response;\n}\nclass DPoPHandler {\n #header;\n #privateKey;\n #publicKey;\n #clockSkew;\n #modifyAssertion;\n #map;\n #jkt;\n constructor(client, keyPair, options) {\n assertPrivateKey(keyPair?.privateKey, '\"DPoP.privateKey\"');\n assertPublicKey(keyPair?.publicKey, '\"DPoP.publicKey\"');\n if (!keyPair.publicKey.extractable) {\n throw CodedTypeError('\"DPoP.publicKey.extractable\" must be true', ERR_INVALID_ARG_VALUE);\n }\n this.#modifyAssertion = options?.[modifyAssertion];\n this.#clockSkew = getClockSkew(client);\n this.#privateKey = keyPair.privateKey;\n this.#publicKey = keyPair.publicKey;\n branded.add(this);\n }\n #get(key) {\n this.#map ||= new Map();\n let item = this.#map.get(key);\n if (item) {\n this.#map.delete(key);\n this.#map.set(key, item);\n }\n return item;\n }\n #set(key, val) {\n this.#map ||= new Map();\n this.#map.delete(key);\n if (this.#map.size === 100) {\n this.#map.delete(this.#map.keys().next().value);\n }\n this.#map.set(key, val);\n }\n async calculateThumbprint() {\n if (!this.#jkt) {\n const jwk = await crypto.subtle.exportKey('jwk', this.#publicKey);\n this.#jkt ||= await calculateJwkThumbprint(jwk);\n }\n return this.#jkt;\n }\n async addProof(url, headers, htm, accessToken) {\n const alg = keyToJws(this.#privateKey);\n this.#header ||= {\n alg,\n typ: 'dpop+jwt',\n jwk: await publicJwk(this.#publicKey, alg),\n };\n const nonce = this.#get(url.origin);\n const now = epochTime() + this.#clockSkew;\n const payload = {\n iat: now,\n jti: randomBytes(),\n htm,\n nonce,\n htu: `${url.origin}${url.pathname}`,\n ath: accessToken\n ? b64u(await crypto.subtle.digest('SHA-256', buf(accessToken)))\n : undefined,\n };\n this.#modifyAssertion?.(this.#header, payload);\n headers.set('dpop', await signJwt(this.#header, payload, this.#privateKey));\n }\n cacheNonce(response, url) {\n try {\n const nonce = response.headers.get('dpop-nonce');\n if (nonce) {\n this.#set(url.origin, nonce);\n }\n }\n catch { }\n }\n}\nexport function isDPoPNonceError(err) {\n if (err instanceof WWWAuthenticateChallengeError) {\n const { 0: challenge, length } = err.cause;\n return (length === 1 && challenge.scheme === 'dpop' && challenge.parameters.error === 'use_dpop_nonce');\n }\n if (err instanceof ResponseBodyError) {\n return err.error === 'use_dpop_nonce';\n }\n return false;\n}\nexport function DPoP(client, keyPair, options) {\n return new DPoPHandler(client, keyPair, options);\n}\nexport class ResponseBodyError extends Error {\n cause;\n code;\n error;\n status;\n error_description;\n response;\n constructor(message, options) {\n super(message, options);\n this.name = this.constructor.name;\n this.code = RESPONSE_BODY_ERROR;\n this.cause = options.cause;\n this.error = options.cause.error;\n this.status = options.response.status;\n this.error_description = options.cause.error_description;\n Object.defineProperty(this, 'response', { enumerable: false, value: options.response });\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nexport class AuthorizationResponseError extends Error {\n cause;\n code;\n error;\n error_description;\n constructor(message, options) {\n super(message, options);\n this.name = this.constructor.name;\n this.code = AUTHORIZATION_RESPONSE_ERROR;\n this.cause = options.cause;\n this.error = options.cause.get('error');\n this.error_description = options.cause.get('error_description') ?? undefined;\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nexport class WWWAuthenticateChallengeError extends Error {\n cause;\n code;\n response;\n status;\n constructor(message, options) {\n super(message, options);\n this.name = this.constructor.name;\n this.code = WWW_AUTHENTICATE_CHALLENGE;\n this.cause = options.cause;\n this.status = options.response.status;\n this.response = options.response;\n Object.defineProperty(this, 'response', { enumerable: false });\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nconst tokenMatch = \"[a-zA-Z0-9!#$%&\\\\'\\\\*\\\\+\\\\-\\\\.\\\\^_`\\\\|~]+\";\nconst token68Match = '[a-zA-Z0-9\\\\-\\\\._\\\\~\\\\+\\\\/]+[=]{0,2}';\nconst quotedMatch = '\"((?:[^\"\\\\\\\\]|\\\\\\\\.)*)\"';\nconst quotedParamMatcher = '(' + tokenMatch + ')\\\\s*=\\\\s*' + quotedMatch;\nconst paramMatcher = '(' + tokenMatch + ')\\\\s*=\\\\s*(' + tokenMatch + ')';\nconst schemeRE = new RegExp('^[,\\\\s]*(' + tokenMatch + ')\\\\s(.*)');\nconst quotedParamRE = new RegExp('^[,\\\\s]*' + quotedParamMatcher + '[,\\\\s]*(.*)');\nconst unquotedParamRE = new RegExp('^[,\\\\s]*' + paramMatcher + '[,\\\\s]*(.*)');\nconst token68ParamRE = new RegExp('^(' + token68Match + ')(?:$|[,\\\\s])(.*)');\nfunction parseWwwAuthenticateChallenges(response) {\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n const header = response.headers.get('www-authenticate');\n if (header === null) {\n return undefined;\n }\n const challenges = [];\n let rest = header;\n while (rest) {\n let match = rest.match(schemeRE);\n const scheme = match?.['1'].toLowerCase();\n rest = match?.['2'];\n if (!scheme) {\n return undefined;\n }\n const parameters = {};\n let token68;\n while (rest) {\n let key;\n let value;\n if ((match = rest.match(quotedParamRE))) {\n ;\n [, key, value, rest] = match;\n if (value.includes('\\\\')) {\n try {\n value = JSON.parse(`\"${value}\"`);\n }\n catch { }\n }\n parameters[key.toLowerCase()] = value;\n continue;\n }\n if ((match = rest.match(unquotedParamRE))) {\n ;\n [, key, value, rest] = match;\n parameters[key.toLowerCase()] = value;\n continue;\n }\n if ((match = rest.match(token68ParamRE))) {\n if (Object.keys(parameters).length) {\n break;\n }\n ;\n [, token68, rest] = match;\n break;\n }\n return undefined;\n }\n const challenge = { scheme, parameters };\n if (token68) {\n challenge.token68 = token68;\n }\n challenges.push(challenge);\n }\n if (!challenges.length) {\n return undefined;\n }\n return challenges;\n}\nexport async function processPushedAuthorizationResponse(as, client, response) {\n assertAs(as);\n assertClient(client);\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n await checkOAuthBodyError(response, 201, 'Pushed Authorization Request Endpoint');\n assertReadableResponse(response);\n const json = await getResponseJsonBody(response);\n assertString(json.request_uri, '\"response\" body \"request_uri\" property', INVALID_RESPONSE, {\n body: json,\n });\n let expiresIn = typeof json.expires_in !== 'number' ? parseFloat(json.expires_in) : json.expires_in;\n assertNumber(expiresIn, true, '\"response\" body \"expires_in\" property', INVALID_RESPONSE, {\n body: json,\n });\n json.expires_in = expiresIn;\n return json;\n}\nasync function parseOAuthResponseErrorBody(response) {\n if (response.status > 399 && response.status < 500) {\n assertReadableResponse(response);\n assertApplicationJson(response);\n try {\n const json = await response.clone().json();\n if (isJsonObject(json) && typeof json.error === 'string' && json.error.length) {\n return json;\n }\n }\n catch { }\n }\n return undefined;\n}\nasync function checkOAuthBodyError(response, expected, label) {\n if (response.status !== expected) {\n checkAuthenticationChallenges(response);\n let err;\n if ((err = await parseOAuthResponseErrorBody(response))) {\n await response.body?.cancel();\n throw new ResponseBodyError('server responded with an error in the response body', {\n cause: err,\n response,\n });\n }\n throw OPE(`\"response\" is not a conform ${label} response (unexpected HTTP status code)`, RESPONSE_IS_NOT_CONFORM, response);\n }\n}\nfunction assertDPoP(option) {\n if (!branded.has(option)) {\n throw CodedTypeError('\"options.DPoP\" is not a valid DPoPHandle', ERR_INVALID_ARG_VALUE);\n }\n}\nasync function resourceRequest(accessToken, method, url, headers, body, options) {\n assertString(accessToken, '\"accessToken\"');\n if (!(url instanceof URL)) {\n throw CodedTypeError('\"url\" must be an instance of URL', ERR_INVALID_ARG_TYPE);\n }\n checkProtocol(url, options?.[allowInsecureRequests] !== true);\n headers = prepareHeaders(headers);\n if (options?.DPoP) {\n assertDPoP(options.DPoP);\n await options.DPoP.addProof(url, headers, method.toUpperCase(), accessToken);\n }\n headers.set('authorization', `${headers.has('dpop') ? 'DPoP' : 'Bearer'} ${accessToken}`);\n const response = await (options?.[customFetch] || fetch)(url.href, {\n body,\n headers: Object.fromEntries(headers.entries()),\n method,\n redirect: 'manual',\n signal: signal(url, options?.signal),\n });\n options?.DPoP?.cacheNonce(response, url);\n return response;\n}\nexport async function protectedResourceRequest(accessToken, method, url, headers, body, options) {\n const response = await resourceRequest(accessToken, method, url, headers, body, options);\n checkAuthenticationChallenges(response);\n return response;\n}\nexport async function userInfoRequest(as, client, accessToken, options) {\n assertAs(as);\n assertClient(client);\n const url = resolveEndpoint(as, 'userinfo_endpoint', client.use_mtls_endpoint_aliases, options?.[allowInsecureRequests] !== true);\n const headers = prepareHeaders(options?.headers);\n if (client.userinfo_signed_response_alg) {\n headers.set('accept', 'application/jwt');\n }\n else {\n headers.set('accept', 'application/json');\n headers.append('accept', 'application/jwt');\n }\n return resourceRequest(accessToken, 'GET', url, headers, null, {\n ...options,\n [clockSkew]: getClockSkew(client),\n });\n}\nlet jwksMap;\nfunction setJwksCache(as, jwks, uat, cache) {\n jwksMap ||= new WeakMap();\n jwksMap.set(as, {\n jwks,\n uat,\n get age() {\n return epochTime() - this.uat;\n },\n });\n if (cache) {\n Object.assign(cache, { jwks: structuredClone(jwks), uat });\n }\n}\nfunction isFreshJwksCache(input) {\n if (typeof input !== 'object' || input === null) {\n return false;\n }\n if (!('uat' in input) || typeof input.uat !== 'number' || epochTime() - input.uat >= 300) {\n return false;\n }\n if (!('jwks' in input) ||\n !isJsonObject(input.jwks) ||\n !Array.isArray(input.jwks.keys) ||\n !Array.prototype.every.call(input.jwks.keys, isJsonObject)) {\n return false;\n }\n return true;\n}\nfunction clearJwksCache(as, cache) {\n jwksMap?.delete(as);\n delete cache?.jwks;\n delete cache?.uat;\n}\nasync function getPublicSigKeyFromIssuerJwksUri(as, options, header) {\n const { alg, kid } = header;\n checkSupportedJwsAlg(header);\n if (!jwksMap?.has(as) && isFreshJwksCache(options?.[jwksCache])) {\n setJwksCache(as, options?.[jwksCache].jwks, options?.[jwksCache].uat);\n }\n let jwks;\n let age;\n if (jwksMap?.has(as)) {\n ;\n ({ jwks, age } = jwksMap.get(as));\n if (age >= 300) {\n clearJwksCache(as, options?.[jwksCache]);\n return getPublicSigKeyFromIssuerJwksUri(as, options, header);\n }\n }\n else {\n jwks = await jwksRequest(as, options).then(processJwksResponse);\n age = 0;\n setJwksCache(as, jwks, epochTime(), options?.[jwksCache]);\n }\n let kty;\n switch (alg.slice(0, 2)) {\n case 'RS':\n case 'PS':\n kty = 'RSA';\n break;\n case 'ES':\n kty = 'EC';\n break;\n case 'Ed':\n kty = 'OKP';\n break;\n case 'ML':\n kty = 'AKP';\n break;\n default:\n throw new UnsupportedOperationError('unsupported JWS algorithm', { cause: { alg } });\n }\n const candidates = jwks.keys.filter((jwk) => {\n if (jwk.kty !== kty) {\n return false;\n }\n if (kid !== undefined && kid !== jwk.kid) {\n return false;\n }\n if (jwk.alg !== undefined && alg !== jwk.alg) {\n return false;\n }\n if (jwk.use !== undefined && jwk.use !== 'sig') {\n return false;\n }\n if (jwk.key_ops?.includes('verify') === false) {\n return false;\n }\n switch (true) {\n case alg === 'ES256' && jwk.crv !== 'P-256':\n case alg === 'ES384' && jwk.crv !== 'P-384':\n case alg === 'ES512' && jwk.crv !== 'P-521':\n case alg === 'Ed25519' && jwk.crv !== 'Ed25519':\n case alg === 'EdDSA' && jwk.crv !== 'Ed25519':\n return false;\n }\n return true;\n });\n const { 0: jwk, length } = candidates;\n if (!length) {\n if (age >= 60) {\n clearJwksCache(as, options?.[jwksCache]);\n return getPublicSigKeyFromIssuerJwksUri(as, options, header);\n }\n throw OPE('error when selecting a JWT verification key, no applicable keys found', KEY_SELECTION, { header, candidates, jwks_uri: new URL(as.jwks_uri) });\n }\n if (length !== 1) {\n throw OPE('error when selecting a JWT verification key, multiple applicable keys found, a \"kid\" JWT Header Parameter is required', KEY_SELECTION, { header, candidates, jwks_uri: new URL(as.jwks_uri) });\n }\n return importJwk(alg, jwk);\n}\nexport const skipSubjectCheck = Symbol();\nexport function getContentType(input) {\n return input.headers.get('content-type')?.split(';')[0];\n}\nexport async function processUserInfoResponse(as, client, expectedSubject, response, options) {\n assertAs(as);\n assertClient(client);\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n checkAuthenticationChallenges(response);\n if (response.status !== 200) {\n throw OPE('\"response\" is not a conform UserInfo Endpoint response (unexpected HTTP status code)', RESPONSE_IS_NOT_CONFORM, response);\n }\n assertReadableResponse(response);\n let json;\n if (getContentType(response) === 'application/jwt') {\n const { claims, jwt } = await validateJwt(await response.text(), checkSigningAlgorithm.bind(undefined, client.userinfo_signed_response_alg, as.userinfo_signing_alg_values_supported, undefined), getClockSkew(client), getClockTolerance(client), options?.[jweDecrypt])\n .then(validateOptionalAudience.bind(undefined, client.client_id))\n .then(validateOptionalIssuer.bind(undefined, as));\n jwtRefs.set(response, jwt);\n json = claims;\n }\n else {\n if (client.userinfo_signed_response_alg) {\n throw OPE('JWT UserInfo Response expected', JWT_USERINFO_EXPECTED, response);\n }\n json = await getResponseJsonBody(response);\n }\n assertString(json.sub, '\"response\" body \"sub\" property', INVALID_RESPONSE, { body: json });\n switch (expectedSubject) {\n case skipSubjectCheck:\n break;\n default:\n assertString(expectedSubject, '\"expectedSubject\"');\n if (json.sub !== expectedSubject) {\n throw OPE('unexpected \"response\" body \"sub\" property value', JSON_ATTRIBUTE_COMPARISON, {\n expected: expectedSubject,\n body: json,\n attribute: 'sub',\n });\n }\n }\n return json;\n}\nasync function authenticatedRequest(as, client, clientAuthentication, url, body, headers, options) {\n await clientAuthentication(as, client, body, headers);\n headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8');\n return (options?.[customFetch] || fetch)(url.href, {\n body,\n headers: Object.fromEntries(headers.entries()),\n method: 'POST',\n redirect: 'manual',\n signal: signal(url, options?.signal),\n });\n}\nasync function tokenEndpointRequest(as, client, clientAuthentication, grantType, parameters, options) {\n const url = resolveEndpoint(as, 'token_endpoint', client.use_mtls_endpoint_aliases, options?.[allowInsecureRequests] !== true);\n parameters.set('grant_type', grantType);\n const headers = prepareHeaders(options?.headers);\n headers.set('accept', 'application/json');\n if (options?.DPoP !== undefined) {\n assertDPoP(options.DPoP);\n await options.DPoP.addProof(url, headers, 'POST');\n }\n const response = await authenticatedRequest(as, client, clientAuthentication, url, parameters, headers, options);\n options?.DPoP?.cacheNonce(response, url);\n return response;\n}\nexport async function refreshTokenGrantRequest(as, client, clientAuthentication, refreshToken, options) {\n assertAs(as);\n assertClient(client);\n assertString(refreshToken, '\"refreshToken\"');\n const parameters = new URLSearchParams(options?.additionalParameters);\n parameters.set('refresh_token', refreshToken);\n return tokenEndpointRequest(as, client, clientAuthentication, 'refresh_token', parameters, options);\n}\nconst idTokenClaims = new WeakMap();\nconst jwtRefs = new WeakMap();\nexport function getValidatedIdTokenClaims(ref) {\n if (!ref.id_token) {\n return undefined;\n }\n const claims = idTokenClaims.get(ref);\n if (!claims) {\n throw CodedTypeError('\"ref\" was already garbage collected or did not resolve from the proper sources', ERR_INVALID_ARG_VALUE);\n }\n return claims;\n}\nexport async function validateApplicationLevelSignature(as, ref, options) {\n assertAs(as);\n if (!jwtRefs.has(ref)) {\n throw CodedTypeError('\"ref\" does not contain a processed JWT Response to verify the signature of', ERR_INVALID_ARG_VALUE);\n }\n const { 0: protectedHeader, 1: payload, 2: encodedSignature } = jwtRefs.get(ref).split('.');\n const header = JSON.parse(buf(b64u(protectedHeader)));\n if (header.alg.startsWith('HS')) {\n throw new UnsupportedOperationError('unsupported JWS algorithm', { cause: { alg: header.alg } });\n }\n let key;\n key = await getPublicSigKeyFromIssuerJwksUri(as, options, header);\n await validateJwsSignature(protectedHeader, payload, key, b64u(encodedSignature));\n}\nasync function processGenericAccessTokenResponse(as, client, response, additionalRequiredIdTokenClaims, decryptFn, recognizedTokenTypes) {\n assertAs(as);\n assertClient(client);\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n await checkOAuthBodyError(response, 200, 'Token Endpoint');\n assertReadableResponse(response);\n const json = await getResponseJsonBody(response);\n assertString(json.access_token, '\"response\" body \"access_token\" property', INVALID_RESPONSE, {\n body: json,\n });\n assertString(json.token_type, '\"response\" body \"token_type\" property', INVALID_RESPONSE, {\n body: json,\n });\n json.token_type = json.token_type.toLowerCase();\n if (json.expires_in !== undefined) {\n let expiresIn = typeof json.expires_in !== 'number' ? parseFloat(json.expires_in) : json.expires_in;\n assertNumber(expiresIn, true, '\"response\" body \"expires_in\" property', INVALID_RESPONSE, {\n body: json,\n });\n json.expires_in = expiresIn;\n }\n if (json.refresh_token !== undefined) {\n assertString(json.refresh_token, '\"response\" body \"refresh_token\" property', INVALID_RESPONSE, {\n body: json,\n });\n }\n if (json.scope !== undefined && typeof json.scope !== 'string') {\n throw OPE('\"response\" body \"scope\" property must be a string', INVALID_RESPONSE, { body: json });\n }\n if (json.id_token !== undefined) {\n assertString(json.id_token, '\"response\" body \"id_token\" property', INVALID_RESPONSE, {\n body: json,\n });\n const requiredClaims = ['aud', 'exp', 'iat', 'iss', 'sub'];\n if (client.require_auth_time === true) {\n requiredClaims.push('auth_time');\n }\n if (client.default_max_age !== undefined) {\n assertNumber(client.default_max_age, true, '\"client.default_max_age\"');\n requiredClaims.push('auth_time');\n }\n if (additionalRequiredIdTokenClaims?.length) {\n requiredClaims.push(...additionalRequiredIdTokenClaims);\n }\n const { claims, jwt } = await validateJwt(json.id_token, checkSigningAlgorithm.bind(undefined, client.id_token_signed_response_alg, as.id_token_signing_alg_values_supported, 'RS256'), getClockSkew(client), getClockTolerance(client), decryptFn)\n .then(validatePresence.bind(undefined, requiredClaims))\n .then(validateIssuer.bind(undefined, as))\n .then(validateAudience.bind(undefined, client.client_id));\n if (Array.isArray(claims.aud) && claims.aud.length !== 1) {\n if (claims.azp === undefined) {\n throw OPE('ID Token \"aud\" (audience) claim includes additional untrusted audiences', JWT_CLAIM_COMPARISON, { claims, claim: 'aud' });\n }\n if (claims.azp !== client.client_id) {\n throw OPE('unexpected ID Token \"azp\" (authorized party) claim value', JWT_CLAIM_COMPARISON, { expected: client.client_id, claims, claim: 'azp' });\n }\n }\n if (claims.auth_time !== undefined) {\n assertNumber(claims.auth_time, true, 'ID Token \"auth_time\" (authentication time)', INVALID_RESPONSE, { claims });\n }\n jwtRefs.set(response, jwt);\n idTokenClaims.set(json, claims);\n }\n if (recognizedTokenTypes?.[json.token_type] !== undefined) {\n recognizedTokenTypes[json.token_type](response, json);\n }\n else if (json.token_type !== 'dpop' && json.token_type !== 'bearer') {\n throw new UnsupportedOperationError('unsupported `token_type` value', { cause: { body: json } });\n }\n return json;\n}\nfunction checkAuthenticationChallenges(response) {\n let challenges;\n if ((challenges = parseWwwAuthenticateChallenges(response))) {\n throw new WWWAuthenticateChallengeError('server responded with a challenge in the WWW-Authenticate HTTP Header', { cause: challenges, response });\n }\n}\nexport async function processRefreshTokenResponse(as, client, response, options) {\n return processGenericAccessTokenResponse(as, client, response, undefined, options?.[jweDecrypt], options?.recognizedTokenTypes);\n}\nfunction validateOptionalAudience(expected, result) {\n if (result.claims.aud !== undefined) {\n return validateAudience(expected, result);\n }\n return result;\n}\nfunction validateAudience(expected, result) {\n if (Array.isArray(result.claims.aud)) {\n if (!result.claims.aud.includes(expected)) {\n throw OPE('unexpected JWT \"aud\" (audience) claim value', JWT_CLAIM_COMPARISON, {\n expected,\n claims: result.claims,\n claim: 'aud',\n });\n }\n }\n else if (result.claims.aud !== expected) {\n throw OPE('unexpected JWT \"aud\" (audience) claim value', JWT_CLAIM_COMPARISON, {\n expected,\n claims: result.claims,\n claim: 'aud',\n });\n }\n return result;\n}\nfunction validateOptionalIssuer(as, result) {\n if (result.claims.iss !== undefined) {\n return validateIssuer(as, result);\n }\n return result;\n}\nfunction validateIssuer(as, result) {\n const expected = as[_expectedIssuer]?.(result) ?? as.issuer;\n if (result.claims.iss !== expected) {\n throw OPE('unexpected JWT \"iss\" (issuer) claim value', JWT_CLAIM_COMPARISON, {\n expected,\n claims: result.claims,\n claim: 'iss',\n });\n }\n return result;\n}\nconst branded = new WeakSet();\nfunction brand(searchParams) {\n branded.add(searchParams);\n return searchParams;\n}\nexport const nopkce = Symbol();\nexport async function authorizationCodeGrantRequest(as, client, clientAuthentication, callbackParameters, redirectUri, codeVerifier, options) {\n assertAs(as);\n assertClient(client);\n if (!branded.has(callbackParameters)) {\n throw CodedTypeError('\"callbackParameters\" must be an instance of URLSearchParams obtained from \"validateAuthResponse()\", or \"validateJwtAuthResponse()', ERR_INVALID_ARG_VALUE);\n }\n assertString(redirectUri, '\"redirectUri\"');\n const code = getURLSearchParameter(callbackParameters, 'code');\n if (!code) {\n throw OPE('no authorization code in \"callbackParameters\"', INVALID_RESPONSE);\n }\n const parameters = new URLSearchParams(options?.additionalParameters);\n parameters.set('redirect_uri', redirectUri);\n parameters.set('code', code);\n if (codeVerifier !== nopkce) {\n assertString(codeVerifier, '\"codeVerifier\"');\n parameters.set('code_verifier', codeVerifier);\n }\n return tokenEndpointRequest(as, client, clientAuthentication, 'authorization_code', parameters, options);\n}\nconst jwtClaimNames = {\n aud: 'audience',\n c_hash: 'code hash',\n client_id: 'client id',\n exp: 'expiration time',\n iat: 'issued at',\n iss: 'issuer',\n jti: 'jwt id',\n nonce: 'nonce',\n s_hash: 'state hash',\n sub: 'subject',\n ath: 'access token hash',\n htm: 'http method',\n htu: 'http uri',\n cnf: 'confirmation',\n auth_time: 'authentication time',\n};\nfunction validatePresence(required, result) {\n for (const claim of required) {\n if (result.claims[claim] === undefined) {\n throw OPE(`JWT \"${claim}\" (${jwtClaimNames[claim]}) claim missing`, INVALID_RESPONSE, {\n claims: result.claims,\n });\n }\n }\n return result;\n}\nexport const expectNoNonce = Symbol();\nexport const skipAuthTimeCheck = Symbol();\nexport async function processAuthorizationCodeResponse(as, client, response, options) {\n if (typeof options?.expectedNonce === 'string' ||\n typeof options?.maxAge === 'number' ||\n options?.requireIdToken) {\n return processAuthorizationCodeOpenIDResponse(as, client, response, options.expectedNonce, options.maxAge, options[jweDecrypt], options.recognizedTokenTypes);\n }\n return processAuthorizationCodeOAuth2Response(as, client, response, options?.[jweDecrypt], options?.recognizedTokenTypes);\n}\nasync function processAuthorizationCodeOpenIDResponse(as, client, response, expectedNonce, maxAge, decryptFn, recognizedTokenTypes) {\n const additionalRequiredClaims = [];\n switch (expectedNonce) {\n case undefined:\n expectedNonce = expectNoNonce;\n break;\n case expectNoNonce:\n break;\n default:\n assertString(expectedNonce, '\"expectedNonce\" argument');\n additionalRequiredClaims.push('nonce');\n }\n maxAge ??= client.default_max_age;\n switch (maxAge) {\n case undefined:\n maxAge = skipAuthTimeCheck;\n break;\n case skipAuthTimeCheck:\n break;\n default:\n assertNumber(maxAge, true, '\"maxAge\" argument');\n additionalRequiredClaims.push('auth_time');\n }\n const result = await processGenericAccessTokenResponse(as, client, response, additionalRequiredClaims, decryptFn, recognizedTokenTypes);\n assertString(result.id_token, '\"response\" body \"id_token\" property', INVALID_RESPONSE, {\n body: result,\n });\n const claims = getValidatedIdTokenClaims(result);\n if (maxAge !== skipAuthTimeCheck) {\n const now = epochTime() + getClockSkew(client);\n const tolerance = getClockTolerance(client);\n if (claims.auth_time + maxAge < now - tolerance) {\n throw OPE('too much time has elapsed since the last End-User authentication', JWT_TIMESTAMP_CHECK, { claims, now, tolerance, claim: 'auth_time' });\n }\n }\n if (expectedNonce === expectNoNonce) {\n if (claims.nonce !== undefined) {\n throw OPE('unexpected ID Token \"nonce\" claim value', JWT_CLAIM_COMPARISON, {\n expected: undefined,\n claims,\n claim: 'nonce',\n });\n }\n }\n else if (claims.nonce !== expectedNonce) {\n throw OPE('unexpected ID Token \"nonce\" claim value', JWT_CLAIM_COMPARISON, {\n expected: expectedNonce,\n claims,\n claim: 'nonce',\n });\n }\n return result;\n}\nasync function processAuthorizationCodeOAuth2Response(as, client, response, decryptFn, recognizedTokenTypes) {\n const result = await processGenericAccessTokenResponse(as, client, response, undefined, decryptFn, recognizedTokenTypes);\n const claims = getValidatedIdTokenClaims(result);\n if (claims) {\n if (client.default_max_age !== undefined) {\n assertNumber(client.default_max_age, true, '\"client.default_max_age\"');\n const now = epochTime() + getClockSkew(client);\n const tolerance = getClockTolerance(client);\n if (claims.auth_time + client.default_max_age < now - tolerance) {\n throw OPE('too much time has elapsed since the last End-User authentication', JWT_TIMESTAMP_CHECK, { claims, now, tolerance, claim: 'auth_time' });\n }\n }\n if (claims.nonce !== undefined) {\n throw OPE('unexpected ID Token \"nonce\" claim value', JWT_CLAIM_COMPARISON, {\n expected: undefined,\n claims,\n claim: 'nonce',\n });\n }\n }\n return result;\n}\nexport const WWW_AUTHENTICATE_CHALLENGE = 'OAUTH_WWW_AUTHENTICATE_CHALLENGE';\nexport const RESPONSE_BODY_ERROR = 'OAUTH_RESPONSE_BODY_ERROR';\nexport const UNSUPPORTED_OPERATION = 'OAUTH_UNSUPPORTED_OPERATION';\nexport const AUTHORIZATION_RESPONSE_ERROR = 'OAUTH_AUTHORIZATION_RESPONSE_ERROR';\nexport const JWT_USERINFO_EXPECTED = 'OAUTH_JWT_USERINFO_EXPECTED';\nexport const PARSE_ERROR = 'OAUTH_PARSE_ERROR';\nexport const INVALID_RESPONSE = 'OAUTH_INVALID_RESPONSE';\nexport const INVALID_REQUEST = 'OAUTH_INVALID_REQUEST';\nexport const RESPONSE_IS_NOT_JSON = 'OAUTH_RESPONSE_IS_NOT_JSON';\nexport const RESPONSE_IS_NOT_CONFORM = 'OAUTH_RESPONSE_IS_NOT_CONFORM';\nexport const HTTP_REQUEST_FORBIDDEN = 'OAUTH_HTTP_REQUEST_FORBIDDEN';\nexport const REQUEST_PROTOCOL_FORBIDDEN = 'OAUTH_REQUEST_PROTOCOL_FORBIDDEN';\nexport const JWT_TIMESTAMP_CHECK = 'OAUTH_JWT_TIMESTAMP_CHECK_FAILED';\nexport const JWT_CLAIM_COMPARISON = 'OAUTH_JWT_CLAIM_COMPARISON_FAILED';\nexport const JSON_ATTRIBUTE_COMPARISON = 'OAUTH_JSON_ATTRIBUTE_COMPARISON_FAILED';\nexport const KEY_SELECTION = 'OAUTH_KEY_SELECTION_FAILED';\nexport const MISSING_SERVER_METADATA = 'OAUTH_MISSING_SERVER_METADATA';\nexport const INVALID_SERVER_METADATA = 'OAUTH_INVALID_SERVER_METADATA';\nfunction checkJwtType(expected, result) {\n if (typeof result.header.typ !== 'string' || normalizeTyp(result.header.typ) !== expected) {\n throw OPE('unexpected JWT \"typ\" header parameter value', INVALID_RESPONSE, {\n header: result.header,\n });\n }\n return result;\n}\nexport async function clientCredentialsGrantRequest(as, client, clientAuthentication, parameters, options) {\n assertAs(as);\n assertClient(client);\n return tokenEndpointRequest(as, client, clientAuthentication, 'client_credentials', new URLSearchParams(parameters), options);\n}\nexport async function genericTokenEndpointRequest(as, client, clientAuthentication, grantType, parameters, options) {\n assertAs(as);\n assertClient(client);\n assertString(grantType, '\"grantType\"');\n return tokenEndpointRequest(as, client, clientAuthentication, grantType, new URLSearchParams(parameters), options);\n}\nexport async function processGenericTokenEndpointResponse(as, client, response, options) {\n return processGenericAccessTokenResponse(as, client, response, undefined, options?.[jweDecrypt], options?.recognizedTokenTypes);\n}\nexport async function processClientCredentialsResponse(as, client, response, options) {\n return processGenericAccessTokenResponse(as, client, response, undefined, options?.[jweDecrypt], options?.recognizedTokenTypes);\n}\nexport async function revocationRequest(as, client, clientAuthentication, token, options) {\n assertAs(as);\n assertClient(client);\n assertString(token, '\"token\"');\n const url = resolveEndpoint(as, 'revocation_endpoint', client.use_mtls_endpoint_aliases, options?.[allowInsecureRequests] !== true);\n const body = new URLSearchParams(options?.additionalParameters);\n body.set('token', token);\n const headers = prepareHeaders(options?.headers);\n headers.delete('accept');\n return authenticatedRequest(as, client, clientAuthentication, url, body, headers, options);\n}\nexport async function processRevocationResponse(response) {\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n await checkOAuthBodyError(response, 200, 'Revocation Endpoint');\n return undefined;\n}\nfunction assertReadableResponse(response) {\n if (response.bodyUsed) {\n throw CodedTypeError('\"response\" body has been used already', ERR_INVALID_ARG_VALUE);\n }\n}\nexport async function introspectionRequest(as, client, clientAuthentication, token, options) {\n assertAs(as);\n assertClient(client);\n assertString(token, '\"token\"');\n const url = resolveEndpoint(as, 'introspection_endpoint', client.use_mtls_endpoint_aliases, options?.[allowInsecureRequests] !== true);\n const body = new URLSearchParams(options?.additionalParameters);\n body.set('token', token);\n const headers = prepareHeaders(options?.headers);\n if (options?.requestJwtResponse ?? client.introspection_signed_response_alg) {\n headers.set('accept', 'application/token-introspection+jwt');\n }\n else {\n headers.set('accept', 'application/json');\n }\n return authenticatedRequest(as, client, clientAuthentication, url, body, headers, options);\n}\nexport async function processIntrospectionResponse(as, client, response, options) {\n assertAs(as);\n assertClient(client);\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n await checkOAuthBodyError(response, 200, 'Introspection Endpoint');\n let json;\n if (getContentType(response) === 'application/token-introspection+jwt') {\n assertReadableResponse(response);\n const { claims, jwt } = await validateJwt(await response.text(), checkSigningAlgorithm.bind(undefined, client.introspection_signed_response_alg, as.introspection_signing_alg_values_supported, 'RS256'), getClockSkew(client), getClockTolerance(client), options?.[jweDecrypt])\n .then(checkJwtType.bind(undefined, 'token-introspection+jwt'))\n .then(validatePresence.bind(undefined, ['aud', 'iat', 'iss']))\n .then(validateIssuer.bind(undefined, as))\n .then(validateAudience.bind(undefined, client.client_id));\n jwtRefs.set(response, jwt);\n if (!isJsonObject(claims.token_introspection)) {\n throw OPE('JWT \"token_introspection\" claim must be a JSON object', INVALID_RESPONSE, {\n claims,\n });\n }\n json = claims.token_introspection;\n }\n else {\n assertReadableResponse(response);\n json = await getResponseJsonBody(response);\n }\n if (typeof json.active !== 'boolean') {\n throw OPE('\"response\" body \"active\" property must be a boolean', INVALID_RESPONSE, {\n body: json,\n });\n }\n return json;\n}\nasync function jwksRequest(as, options) {\n assertAs(as);\n const url = resolveEndpoint(as, 'jwks_uri', false, options?.[allowInsecureRequests] !== true);\n const headers = prepareHeaders(options?.headers);\n headers.set('accept', 'application/json');\n headers.append('accept', 'application/jwk-set+json');\n return (options?.[customFetch] || fetch)(url.href, {\n body: undefined,\n headers: Object.fromEntries(headers.entries()),\n method: 'GET',\n redirect: 'manual',\n signal: signal(url, options?.signal),\n });\n}\nasync function processJwksResponse(response) {\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n if (response.status !== 200) {\n throw OPE('\"response\" is not a conform JSON Web Key Set response (unexpected HTTP status code)', RESPONSE_IS_NOT_CONFORM, response);\n }\n assertReadableResponse(response);\n const json = await getResponseJsonBody(response, (response) => assertContentTypes(response, 'application/json', 'application/jwk-set+json'));\n if (!Array.isArray(json.keys)) {\n throw OPE('\"response\" body \"keys\" property must be an array', INVALID_RESPONSE, { body: json });\n }\n if (!Array.prototype.every.call(json.keys, isJsonObject)) {\n throw OPE('\"response\" body \"keys\" property members must be JWK formatted objects', INVALID_RESPONSE, { body: json });\n }\n return json;\n}\nfunction supported(alg) {\n switch (alg) {\n case 'PS256':\n case 'ES256':\n case 'RS256':\n case 'PS384':\n case 'ES384':\n case 'RS384':\n case 'PS512':\n case 'ES512':\n case 'RS512':\n case 'Ed25519':\n case 'EdDSA':\n case 'ML-DSA-44':\n case 'ML-DSA-65':\n case 'ML-DSA-87':\n return true;\n default:\n return false;\n }\n}\nfunction checkSupportedJwsAlg(header) {\n if (!supported(header.alg)) {\n throw new UnsupportedOperationError('unsupported JWS \"alg\" identifier', {\n cause: { alg: header.alg },\n });\n }\n}\nfunction checkRsaKeyAlgorithm(key) {\n const { algorithm } = key;\n if (typeof algorithm.modulusLength !== 'number' || algorithm.modulusLength < 2048) {\n throw new UnsupportedOperationError(`unsupported ${algorithm.name} modulusLength`, {\n cause: key,\n });\n }\n}\nfunction ecdsaHashName(key) {\n const { algorithm } = key;\n switch (algorithm.namedCurve) {\n case 'P-256':\n return 'SHA-256';\n case 'P-384':\n return 'SHA-384';\n case 'P-521':\n return 'SHA-512';\n default:\n throw new UnsupportedOperationError('unsupported ECDSA namedCurve', { cause: key });\n }\n}\nfunction keyToSubtle(key) {\n switch (key.algorithm.name) {\n case 'ECDSA':\n return {\n name: key.algorithm.name,\n hash: ecdsaHashName(key),\n };\n case 'RSA-PSS': {\n checkRsaKeyAlgorithm(key);\n switch (key.algorithm.hash.name) {\n case 'SHA-256':\n case 'SHA-384':\n case 'SHA-512':\n return {\n name: key.algorithm.name,\n saltLength: parseInt(key.algorithm.hash.name.slice(-3), 10) >> 3,\n };\n default:\n throw new UnsupportedOperationError('unsupported RSA-PSS hash name', { cause: key });\n }\n }\n case 'RSASSA-PKCS1-v1_5':\n checkRsaKeyAlgorithm(key);\n return key.algorithm.name;\n case 'ML-DSA-44':\n case 'ML-DSA-65':\n case 'ML-DSA-87':\n case 'Ed25519':\n return key.algorithm.name;\n }\n throw new UnsupportedOperationError('unsupported CryptoKey algorithm name', { cause: key });\n}\nasync function validateJwsSignature(protectedHeader, payload, key, signature) {\n const data = buf(`${protectedHeader}.${payload}`);\n const algorithm = keyToSubtle(key);\n const verified = await crypto.subtle.verify(algorithm, key, signature, data);\n if (!verified) {\n throw OPE('JWT signature verification failed', INVALID_RESPONSE, {\n key,\n data,\n signature,\n algorithm,\n });\n }\n}\nasync function validateJwt(jws, checkAlg, clockSkew, clockTolerance, decryptJwt) {\n let { 0: protectedHeader, 1: payload, length } = jws.split('.');\n if (length === 5) {\n if (decryptJwt !== undefined) {\n jws = await decryptJwt(jws);\n ({ 0: protectedHeader, 1: payload, length } = jws.split('.'));\n }\n else {\n throw new UnsupportedOperationError('JWE decryption is not configured', { cause: jws });\n }\n }\n if (length !== 3) {\n throw OPE('Invalid JWT', INVALID_RESPONSE, jws);\n }\n let header;\n try {\n header = JSON.parse(buf(b64u(protectedHeader)));\n }\n catch (cause) {\n throw OPE('failed to parse JWT Header body as base64url encoded JSON', PARSE_ERROR, cause);\n }\n if (!isJsonObject(header)) {\n throw OPE('JWT Header must be a top level object', INVALID_RESPONSE, jws);\n }\n checkAlg(header);\n if (header.crit !== undefined) {\n throw new UnsupportedOperationError('no JWT \"crit\" header parameter extensions are supported', {\n cause: { header },\n });\n }\n let claims;\n try {\n claims = JSON.parse(buf(b64u(payload)));\n }\n catch (cause) {\n throw OPE('failed to parse JWT Payload body as base64url encoded JSON', PARSE_ERROR, cause);\n }\n if (!isJsonObject(claims)) {\n throw OPE('JWT Payload must be a top level object', INVALID_RESPONSE, jws);\n }\n const now = epochTime() + clockSkew;\n if (claims.exp !== undefined) {\n if (typeof claims.exp !== 'number') {\n throw OPE('unexpected JWT \"exp\" (expiration time) claim type', INVALID_RESPONSE, { claims });\n }\n if (claims.exp <= now - clockTolerance) {\n throw OPE('unexpected JWT \"exp\" (expiration time) claim value, expiration is past current timestamp', JWT_TIMESTAMP_CHECK, { claims, now, tolerance: clockTolerance, claim: 'exp' });\n }\n }\n if (claims.iat !== undefined) {\n if (typeof claims.iat !== 'number') {\n throw OPE('unexpected JWT \"iat\" (issued at) claim type', INVALID_RESPONSE, { claims });\n }\n }\n if (claims.iss !== undefined) {\n if (typeof claims.iss !== 'string') {\n throw OPE('unexpected JWT \"iss\" (issuer) claim type', INVALID_RESPONSE, { claims });\n }\n }\n if (claims.nbf !== undefined) {\n if (typeof claims.nbf !== 'number') {\n throw OPE('unexpected JWT \"nbf\" (not before) claim type', INVALID_RESPONSE, { claims });\n }\n if (claims.nbf > now + clockTolerance) {\n throw OPE('unexpected JWT \"nbf\" (not before) claim value', JWT_TIMESTAMP_CHECK, {\n claims,\n now,\n tolerance: clockTolerance,\n claim: 'nbf',\n });\n }\n }\n if (claims.aud !== undefined) {\n if (typeof claims.aud !== 'string' && !Array.isArray(claims.aud)) {\n throw OPE('unexpected JWT \"aud\" (audience) claim type', INVALID_RESPONSE, { claims });\n }\n }\n return { header, claims, jwt: jws };\n}\nexport async function validateJwtAuthResponse(as, client, parameters, expectedState, options) {\n assertAs(as);\n assertClient(client);\n if (parameters instanceof URL) {\n parameters = parameters.searchParams;\n }\n if (!(parameters instanceof URLSearchParams)) {\n throw CodedTypeError('\"parameters\" must be an instance of URLSearchParams, or URL', ERR_INVALID_ARG_TYPE);\n }\n const response = getURLSearchParameter(parameters, 'response');\n if (!response) {\n throw OPE('\"parameters\" does not contain a JARM response', INVALID_RESPONSE);\n }\n const { claims, header, jwt } = await validateJwt(response, checkSigningAlgorithm.bind(undefined, client.authorization_signed_response_alg, as.authorization_signing_alg_values_supported, 'RS256'), getClockSkew(client), getClockTolerance(client), options?.[jweDecrypt])\n .then(validatePresence.bind(undefined, ['aud', 'exp', 'iss']))\n .then(validateIssuer.bind(undefined, as))\n .then(validateAudience.bind(undefined, client.client_id));\n const { 0: protectedHeader, 1: payload, 2: encodedSignature } = jwt.split('.');\n const signature = b64u(encodedSignature);\n const key = await getPublicSigKeyFromIssuerJwksUri(as, options, header);\n await validateJwsSignature(protectedHeader, payload, key, signature);\n const result = new URLSearchParams();\n for (const [key, value] of Object.entries(claims)) {\n if (typeof value === 'string' && key !== 'aud') {\n result.set(key, value);\n }\n }\n return validateAuthResponse(as, client, result, expectedState);\n}\nasync function idTokenHash(data, header, claimName) {\n let algorithm;\n switch (header.alg) {\n case 'RS256':\n case 'PS256':\n case 'ES256':\n algorithm = 'SHA-256';\n break;\n case 'RS384':\n case 'PS384':\n case 'ES384':\n algorithm = 'SHA-384';\n break;\n case 'RS512':\n case 'PS512':\n case 'ES512':\n case 'Ed25519':\n case 'EdDSA':\n algorithm = 'SHA-512';\n break;\n case 'ML-DSA-44':\n case 'ML-DSA-65':\n case 'ML-DSA-87':\n algorithm = { name: 'cSHAKE256', length: 512 };\n break;\n default:\n throw new UnsupportedOperationError(`unsupported JWS algorithm for ${claimName} calculation`, { cause: { alg: header.alg } });\n }\n const digest = await crypto.subtle.digest(algorithm, buf(data));\n return b64u(digest.slice(0, digest.byteLength / 2));\n}\nasync function idTokenHashMatches(data, actual, header, claimName) {\n const expected = await idTokenHash(data, header, claimName);\n return actual === expected;\n}\nexport async function validateDetachedSignatureResponse(as, client, parameters, expectedNonce, expectedState, maxAge, options) {\n return validateHybridResponse(as, client, parameters, expectedNonce, expectedState, maxAge, options, true);\n}\nexport async function validateCodeIdTokenResponse(as, client, parameters, expectedNonce, expectedState, maxAge, options) {\n return validateHybridResponse(as, client, parameters, expectedNonce, expectedState, maxAge, options, false);\n}\nasync function consumeStream(request) {\n if (request.bodyUsed) {\n throw CodedTypeError('form_post Request instances must contain a readable body', ERR_INVALID_ARG_VALUE, { cause: request });\n }\n return request.text();\n}\nexport async function formPostResponse(request) {\n if (request.method !== 'POST') {\n throw CodedTypeError('form_post responses are expected to use the POST method', ERR_INVALID_ARG_VALUE, { cause: request });\n }\n if (getContentType(request) !== 'application/x-www-form-urlencoded') {\n throw CodedTypeError('form_post responses are expected to use the application/x-www-form-urlencoded content-type', ERR_INVALID_ARG_VALUE, { cause: request });\n }\n return consumeStream(request);\n}\nasync function validateHybridResponse(as, client, parameters, expectedNonce, expectedState, maxAge, options, fapi) {\n assertAs(as);\n assertClient(client);\n if (parameters instanceof URL) {\n if (!parameters.hash.length) {\n throw CodedTypeError('\"parameters\" as an instance of URL must contain a hash (fragment) with the Authorization Response parameters', ERR_INVALID_ARG_VALUE);\n }\n parameters = new URLSearchParams(parameters.hash.slice(1));\n }\n else if (looseInstanceOf(parameters, Request)) {\n parameters = new URLSearchParams(await formPostResponse(parameters));\n }\n else if (parameters instanceof URLSearchParams) {\n parameters = new URLSearchParams(parameters);\n }\n else {\n throw CodedTypeError('\"parameters\" must be an instance of URLSearchParams, URL, or Response', ERR_INVALID_ARG_TYPE);\n }\n const id_token = getURLSearchParameter(parameters, 'id_token');\n parameters.delete('id_token');\n switch (expectedState) {\n case undefined:\n case expectNoState:\n break;\n default:\n assertString(expectedState, '\"expectedState\" argument');\n }\n const result = validateAuthResponse({\n ...as,\n authorization_response_iss_parameter_supported: false,\n }, client, parameters, expectedState);\n if (!id_token) {\n throw OPE('\"parameters\" does not contain an ID Token', INVALID_RESPONSE);\n }\n const code = getURLSearchParameter(parameters, 'code');\n if (!code) {\n throw OPE('\"parameters\" does not contain an Authorization Code', INVALID_RESPONSE);\n }\n const requiredClaims = [\n 'aud',\n 'exp',\n 'iat',\n 'iss',\n 'sub',\n 'nonce',\n 'c_hash',\n ];\n const state = parameters.get('state');\n if (fapi && (typeof expectedState === 'string' || state !== null)) {\n requiredClaims.push('s_hash');\n }\n if (maxAge !== undefined) {\n assertNumber(maxAge, true, '\"maxAge\" argument');\n }\n else if (client.default_max_age !== undefined) {\n assertNumber(client.default_max_age, true, '\"client.default_max_age\"');\n }\n maxAge ??= client.default_max_age ?? skipAuthTimeCheck;\n if (client.require_auth_time || maxAge !== skipAuthTimeCheck) {\n requiredClaims.push('auth_time');\n }\n const { claims, header, jwt } = await validateJwt(id_token, checkSigningAlgorithm.bind(undefined, client.id_token_signed_response_alg, as.id_token_signing_alg_values_supported, 'RS256'), getClockSkew(client), getClockTolerance(client), options?.[jweDecrypt])\n .then(validatePresence.bind(undefined, requiredClaims))\n .then(validateIssuer.bind(undefined, as))\n .then(validateAudience.bind(undefined, client.client_id));\n const clockSkew = getClockSkew(client);\n const now = epochTime() + clockSkew;\n if (claims.iat < now - 3600) {\n throw OPE('unexpected JWT \"iat\" (issued at) claim value, it is too far in the past', JWT_TIMESTAMP_CHECK, { now, claims, claim: 'iat' });\n }\n assertString(claims.c_hash, 'ID Token \"c_hash\" (code hash) claim value', INVALID_RESPONSE, {\n claims,\n });\n if (claims.auth_time !== undefined) {\n assertNumber(claims.auth_time, true, 'ID Token \"auth_time\" (authentication time)', INVALID_RESPONSE, { claims });\n }\n if (maxAge !== skipAuthTimeCheck) {\n const now = epochTime() + getClockSkew(client);\n const tolerance = getClockTolerance(client);\n if (claims.auth_time + maxAge < now - tolerance) {\n throw OPE('too much time has elapsed since the last End-User authentication', JWT_TIMESTAMP_CHECK, { claims, now, tolerance, claim: 'auth_time' });\n }\n }\n assertString(expectedNonce, '\"expectedNonce\" argument');\n if (claims.nonce !== expectedNonce) {\n throw OPE('unexpected ID Token \"nonce\" claim value', JWT_CLAIM_COMPARISON, {\n expected: expectedNonce,\n claims,\n claim: 'nonce',\n });\n }\n if (Array.isArray(claims.aud) && claims.aud.length !== 1) {\n if (claims.azp === undefined) {\n throw OPE('ID Token \"aud\" (audience) claim includes additional untrusted audiences', JWT_CLAIM_COMPARISON, { claims, claim: 'aud' });\n }\n if (claims.azp !== client.client_id) {\n throw OPE('unexpected ID Token \"azp\" (authorized party) claim value', JWT_CLAIM_COMPARISON, {\n expected: client.client_id,\n claims,\n claim: 'azp',\n });\n }\n }\n const { 0: protectedHeader, 1: payload, 2: encodedSignature } = jwt.split('.');\n const signature = b64u(encodedSignature);\n const key = await getPublicSigKeyFromIssuerJwksUri(as, options, header);\n await validateJwsSignature(protectedHeader, payload, key, signature);\n if ((await idTokenHashMatches(code, claims.c_hash, header, 'c_hash')) !== true) {\n throw OPE('invalid ID Token \"c_hash\" (code hash) claim value', JWT_CLAIM_COMPARISON, {\n code,\n alg: header.alg,\n claim: 'c_hash',\n claims,\n });\n }\n if ((fapi && state !== null) || claims.s_hash !== undefined) {\n assertString(claims.s_hash, 'ID Token \"s_hash\" (state hash) claim value', INVALID_RESPONSE, {\n claims,\n });\n assertString(state, '\"state\" response parameter', INVALID_RESPONSE, { parameters });\n if ((await idTokenHashMatches(state, claims.s_hash, header, 's_hash')) !== true) {\n throw OPE('invalid ID Token \"s_hash\" (state hash) claim value', JWT_CLAIM_COMPARISON, {\n state,\n alg: header.alg,\n claim: 's_hash',\n claims,\n });\n }\n }\n return result;\n}\nfunction checkSigningAlgorithm(client, issuer, fallback, header) {\n if (client !== undefined) {\n if (typeof client === 'string' ? header.alg !== client : !client.includes(header.alg)) {\n throw OPE('unexpected JWT \"alg\" header parameter', INVALID_RESPONSE, {\n header,\n expected: client,\n reason: 'client configuration',\n });\n }\n return;\n }\n if (Array.isArray(issuer)) {\n if (!issuer.includes(header.alg)) {\n throw OPE('unexpected JWT \"alg\" header parameter', INVALID_RESPONSE, {\n header,\n expected: issuer,\n reason: 'authorization server metadata',\n });\n }\n return;\n }\n if (fallback !== undefined) {\n if (typeof fallback === 'string'\n ? header.alg !== fallback\n : typeof fallback === 'function'\n ? !fallback(header.alg)\n : !fallback.includes(header.alg)) {\n throw OPE('unexpected JWT \"alg\" header parameter', INVALID_RESPONSE, {\n header,\n expected: fallback,\n reason: 'default value',\n });\n }\n return;\n }\n throw OPE('missing client or server configuration to verify used JWT \"alg\" header parameter', undefined, { client, issuer, fallback });\n}\nfunction getURLSearchParameter(parameters, name) {\n const { 0: value, length } = parameters.getAll(name);\n if (length > 1) {\n throw OPE(`\"${name}\" parameter must be provided only once`, INVALID_RESPONSE);\n }\n return value;\n}\nexport const skipStateCheck = Symbol();\nexport const expectNoState = Symbol();\nexport function validateAuthResponse(as, client, parameters, expectedState) {\n assertAs(as);\n assertClient(client);\n if (parameters instanceof URL) {\n parameters = parameters.searchParams;\n }\n if (!(parameters instanceof URLSearchParams)) {\n throw CodedTypeError('\"parameters\" must be an instance of URLSearchParams, or URL', ERR_INVALID_ARG_TYPE);\n }\n if (getURLSearchParameter(parameters, 'response')) {\n throw OPE('\"parameters\" contains a JARM response, use validateJwtAuthResponse() instead of validateAuthResponse()', INVALID_RESPONSE, { parameters });\n }\n const iss = getURLSearchParameter(parameters, 'iss');\n const state = getURLSearchParameter(parameters, 'state');\n if (!iss && as.authorization_response_iss_parameter_supported) {\n throw OPE('response parameter \"iss\" (issuer) missing', INVALID_RESPONSE, { parameters });\n }\n if (iss && iss !== as.issuer) {\n throw OPE('unexpected \"iss\" (issuer) response parameter value', INVALID_RESPONSE, {\n expected: as.issuer,\n parameters,\n });\n }\n switch (expectedState) {\n case undefined:\n case expectNoState:\n if (state !== undefined) {\n throw OPE('unexpected \"state\" response parameter encountered', INVALID_RESPONSE, {\n expected: undefined,\n parameters,\n });\n }\n break;\n case skipStateCheck:\n break;\n default:\n assertString(expectedState, '\"expectedState\" argument');\n if (state !== expectedState) {\n throw OPE(state === undefined\n ? 'response parameter \"state\" missing'\n : 'unexpected \"state\" response parameter value', INVALID_RESPONSE, { expected: expectedState, parameters });\n }\n }\n const error = getURLSearchParameter(parameters, 'error');\n if (error) {\n throw new AuthorizationResponseError('authorization response from the server is an error', {\n cause: parameters,\n });\n }\n const id_token = getURLSearchParameter(parameters, 'id_token');\n const token = getURLSearchParameter(parameters, 'token');\n if (id_token !== undefined || token !== undefined) {\n throw new UnsupportedOperationError('implicit and hybrid flows are not supported');\n }\n return brand(new URLSearchParams(parameters));\n}\nfunction algToSubtle(alg) {\n switch (alg) {\n case 'PS256':\n case 'PS384':\n case 'PS512':\n return { name: 'RSA-PSS', hash: `SHA-${alg.slice(-3)}` };\n case 'RS256':\n case 'RS384':\n case 'RS512':\n return { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${alg.slice(-3)}` };\n case 'ES256':\n case 'ES384':\n return { name: 'ECDSA', namedCurve: `P-${alg.slice(-3)}` };\n case 'ES512':\n return { name: 'ECDSA', namedCurve: 'P-521' };\n case 'EdDSA':\n return 'Ed25519';\n case 'Ed25519':\n case 'ML-DSA-44':\n case 'ML-DSA-65':\n case 'ML-DSA-87':\n return alg;\n default:\n throw new UnsupportedOperationError('unsupported JWS algorithm', { cause: { alg } });\n }\n}\nasync function importJwk(alg, jwk) {\n const { ext, key_ops, use, ...key } = jwk;\n return crypto.subtle.importKey('jwk', key, algToSubtle(alg), true, ['verify']);\n}\nexport async function deviceAuthorizationRequest(as, client, clientAuthentication, parameters, options) {\n assertAs(as);\n assertClient(client);\n const url = resolveEndpoint(as, 'device_authorization_endpoint', client.use_mtls_endpoint_aliases, options?.[allowInsecureRequests] !== true);\n const body = new URLSearchParams(parameters);\n body.set('client_id', client.client_id);\n const headers = prepareHeaders(options?.headers);\n headers.set('accept', 'application/json');\n return authenticatedRequest(as, client, clientAuthentication, url, body, headers, options);\n}\nexport async function processDeviceAuthorizationResponse(as, client, response) {\n assertAs(as);\n assertClient(client);\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n await checkOAuthBodyError(response, 200, 'Device Authorization Endpoint');\n assertReadableResponse(response);\n const json = await getResponseJsonBody(response);\n assertString(json.device_code, '\"response\" body \"device_code\" property', INVALID_RESPONSE, {\n body: json,\n });\n assertString(json.user_code, '\"response\" body \"user_code\" property', INVALID_RESPONSE, {\n body: json,\n });\n assertString(json.verification_uri, '\"response\" body \"verification_uri\" property', INVALID_RESPONSE, { body: json });\n let expiresIn = typeof json.expires_in !== 'number' ? parseFloat(json.expires_in) : json.expires_in;\n assertNumber(expiresIn, true, '\"response\" body \"expires_in\" property', INVALID_RESPONSE, {\n body: json,\n });\n json.expires_in = expiresIn;\n if (json.verification_uri_complete !== undefined) {\n assertString(json.verification_uri_complete, '\"response\" body \"verification_uri_complete\" property', INVALID_RESPONSE, { body: json });\n }\n if (json.interval !== undefined) {\n assertNumber(json.interval, false, '\"response\" body \"interval\" property', INVALID_RESPONSE, {\n body: json,\n });\n }\n return json;\n}\nexport async function deviceCodeGrantRequest(as, client, clientAuthentication, deviceCode, options) {\n assertAs(as);\n assertClient(client);\n assertString(deviceCode, '\"deviceCode\"');\n const parameters = new URLSearchParams(options?.additionalParameters);\n parameters.set('device_code', deviceCode);\n return tokenEndpointRequest(as, client, clientAuthentication, 'urn:ietf:params:oauth:grant-type:device_code', parameters, options);\n}\nexport async function processDeviceCodeResponse(as, client, response, options) {\n return processGenericAccessTokenResponse(as, client, response, undefined, options?.[jweDecrypt], options?.recognizedTokenTypes);\n}\nexport async function generateKeyPair(alg, options) {\n assertString(alg, '\"alg\"');\n const algorithm = algToSubtle(alg);\n if (alg.startsWith('PS') || alg.startsWith('RS')) {\n Object.assign(algorithm, {\n modulusLength: options?.modulusLength ?? 2048,\n publicExponent: new Uint8Array([0x01, 0x00, 0x01]),\n });\n }\n return crypto.subtle.generateKey(algorithm, options?.extractable ?? false, [\n 'sign',\n 'verify',\n ]);\n}\nfunction normalizeHtu(htu) {\n const url = new URL(htu);\n url.search = '';\n url.hash = '';\n return url.href;\n}\nasync function validateDPoP(request, accessToken, accessTokenClaims, options) {\n const headerValue = request.headers.get('dpop');\n if (headerValue === null) {\n throw OPE('operation indicated DPoP use but the request has no DPoP HTTP Header', INVALID_REQUEST, { headers: request.headers });\n }\n if (request.headers.get('authorization')?.toLowerCase().startsWith('dpop ') === false) {\n throw OPE(`operation indicated DPoP use but the request's Authorization HTTP Header scheme is not DPoP`, INVALID_REQUEST, { headers: request.headers });\n }\n if (typeof accessTokenClaims.cnf?.jkt !== 'string') {\n throw OPE('operation indicated DPoP use but the JWT Access Token has no jkt confirmation claim', INVALID_REQUEST, { claims: accessTokenClaims });\n }\n const clockSkew = getClockSkew(options);\n const proof = await validateJwt(headerValue, checkSigningAlgorithm.bind(undefined, options?.signingAlgorithms, undefined, supported), clockSkew, getClockTolerance(options), undefined)\n .then(checkJwtType.bind(undefined, 'dpop+jwt'))\n .then(validatePresence.bind(undefined, ['iat', 'jti', 'ath', 'htm', 'htu']));\n const now = epochTime() + clockSkew;\n const diff = Math.abs(now - proof.claims.iat);\n if (diff > 300) {\n throw OPE('DPoP Proof iat is not recent enough', JWT_TIMESTAMP_CHECK, {\n now,\n claims: proof.claims,\n claim: 'iat',\n });\n }\n if (proof.claims.htm !== request.method) {\n throw OPE('DPoP Proof htm mismatch', JWT_CLAIM_COMPARISON, {\n expected: request.method,\n claims: proof.claims,\n claim: 'htm',\n });\n }\n if (typeof proof.claims.htu !== 'string' ||\n normalizeHtu(proof.claims.htu) !== normalizeHtu(request.url)) {\n throw OPE('DPoP Proof htu mismatch', JWT_CLAIM_COMPARISON, {\n expected: normalizeHtu(request.url),\n claims: proof.claims,\n claim: 'htu',\n });\n }\n {\n const expected = b64u(await crypto.subtle.digest('SHA-256', buf(accessToken)));\n if (proof.claims.ath !== expected) {\n throw OPE('DPoP Proof ath mismatch', JWT_CLAIM_COMPARISON, {\n expected,\n claims: proof.claims,\n claim: 'ath',\n });\n }\n }\n {\n const expected = await calculateJwkThumbprint(proof.header.jwk);\n if (accessTokenClaims.cnf.jkt !== expected) {\n throw OPE('JWT Access Token confirmation mismatch', JWT_CLAIM_COMPARISON, {\n expected,\n claims: accessTokenClaims,\n claim: 'cnf.jkt',\n });\n }\n }\n const { 0: protectedHeader, 1: payload, 2: encodedSignature } = headerValue.split('.');\n const signature = b64u(encodedSignature);\n const { jwk, alg } = proof.header;\n if (!jwk) {\n throw OPE('DPoP Proof is missing the jwk header parameter', INVALID_REQUEST, {\n header: proof.header,\n });\n }\n const key = await importJwk(alg, jwk);\n if (key.type !== 'public') {\n throw OPE('DPoP Proof jwk header parameter must contain a public key', INVALID_REQUEST, {\n header: proof.header,\n });\n }\n await validateJwsSignature(protectedHeader, payload, key, signature);\n}\nexport async function validateJwtAccessToken(as, request, expectedAudience, options) {\n assertAs(as);\n if (!looseInstanceOf(request, Request)) {\n throw CodedTypeError('\"request\" must be an instance of Request', ERR_INVALID_ARG_TYPE);\n }\n assertString(expectedAudience, '\"expectedAudience\"');\n const authorization = request.headers.get('authorization');\n if (authorization === null) {\n throw OPE('\"request\" is missing an Authorization HTTP Header', INVALID_REQUEST, {\n headers: request.headers,\n });\n }\n let { 0: scheme, 1: accessToken, length } = authorization.split(' ');\n scheme = scheme.toLowerCase();\n switch (scheme) {\n case 'dpop':\n case 'bearer':\n break;\n default:\n throw new UnsupportedOperationError('unsupported Authorization HTTP Header scheme', {\n cause: { headers: request.headers },\n });\n }\n if (length !== 2) {\n throw OPE('invalid Authorization HTTP Header format', INVALID_REQUEST, {\n headers: request.headers,\n });\n }\n const requiredClaims = [\n 'iss',\n 'exp',\n 'aud',\n 'sub',\n 'iat',\n 'jti',\n 'client_id',\n ];\n if (options?.requireDPoP || scheme === 'dpop' || request.headers.has('dpop')) {\n requiredClaims.push('cnf');\n }\n const { claims, header } = await validateJwt(accessToken, checkSigningAlgorithm.bind(undefined, options?.signingAlgorithms, undefined, supported), getClockSkew(options), getClockTolerance(options), undefined)\n .then(checkJwtType.bind(undefined, 'at+jwt'))\n .then(validatePresence.bind(undefined, requiredClaims))\n .then(validateIssuer.bind(undefined, as))\n .then(validateAudience.bind(undefined, expectedAudience))\n .catch(reassignRSCode);\n for (const claim of ['client_id', 'jti', 'sub']) {\n if (typeof claims[claim] !== 'string') {\n throw OPE(`unexpected JWT \"${claim}\" claim type`, INVALID_REQUEST, { claims });\n }\n }\n if ('cnf' in claims) {\n if (!isJsonObject(claims.cnf)) {\n throw OPE('unexpected JWT \"cnf\" (confirmation) claim value', INVALID_REQUEST, { claims });\n }\n const { 0: cnf, length } = Object.keys(claims.cnf);\n if (length) {\n if (length !== 1) {\n throw new UnsupportedOperationError('multiple confirmation claims are not supported', {\n cause: { claims },\n });\n }\n if (cnf !== 'jkt') {\n throw new UnsupportedOperationError('unsupported JWT Confirmation method', {\n cause: { claims },\n });\n }\n }\n }\n const { 0: protectedHeader, 1: payload, 2: encodedSignature } = accessToken.split('.');\n const signature = b64u(encodedSignature);\n const key = await getPublicSigKeyFromIssuerJwksUri(as, options, header);\n await validateJwsSignature(protectedHeader, payload, key, signature);\n if (options?.requireDPoP ||\n scheme === 'dpop' ||\n claims.cnf?.jkt !== undefined ||\n request.headers.has('dpop')) {\n await validateDPoP(request, accessToken, claims, options).catch(reassignRSCode);\n }\n return claims;\n}\nfunction reassignRSCode(err) {\n if (err instanceof OperationProcessingError && err?.code === INVALID_REQUEST) {\n err.code = INVALID_RESPONSE;\n }\n throw err;\n}\nexport async function backchannelAuthenticationRequest(as, client, clientAuthentication, parameters, options) {\n assertAs(as);\n assertClient(client);\n const url = resolveEndpoint(as, 'backchannel_authentication_endpoint', client.use_mtls_endpoint_aliases, options?.[allowInsecureRequests] !== true);\n const body = new URLSearchParams(parameters);\n body.set('client_id', client.client_id);\n const headers = prepareHeaders(options?.headers);\n headers.set('accept', 'application/json');\n return authenticatedRequest(as, client, clientAuthentication, url, body, headers, options);\n}\nexport async function processBackchannelAuthenticationResponse(as, client, response) {\n assertAs(as);\n assertClient(client);\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n await checkOAuthBodyError(response, 200, 'Backchannel Authentication Endpoint');\n assertReadableResponse(response);\n const json = await getResponseJsonBody(response);\n assertString(json.auth_req_id, '\"response\" body \"auth_req_id\" property', INVALID_RESPONSE, {\n body: json,\n });\n let expiresIn = typeof json.expires_in !== 'number' ? parseFloat(json.expires_in) : json.expires_in;\n assertNumber(expiresIn, true, '\"response\" body \"expires_in\" property', INVALID_RESPONSE, {\n body: json,\n });\n json.expires_in = expiresIn;\n if (json.interval !== undefined) {\n assertNumber(json.interval, false, '\"response\" body \"interval\" property', INVALID_RESPONSE, {\n body: json,\n });\n }\n return json;\n}\nexport async function backchannelAuthenticationGrantRequest(as, client, clientAuthentication, authReqId, options) {\n assertAs(as);\n assertClient(client);\n assertString(authReqId, '\"authReqId\"');\n const parameters = new URLSearchParams(options?.additionalParameters);\n parameters.set('auth_req_id', authReqId);\n return tokenEndpointRequest(as, client, clientAuthentication, 'urn:openid:params:grant-type:ciba', parameters, options);\n}\nexport async function processBackchannelAuthenticationGrantResponse(as, client, response, options) {\n return processGenericAccessTokenResponse(as, client, response, undefined, options?.[jweDecrypt], options?.recognizedTokenTypes);\n}\nexport async function dynamicClientRegistrationRequest(as, metadata, options) {\n assertAs(as);\n const url = resolveEndpoint(as, 'registration_endpoint', metadata.use_mtls_endpoint_aliases, options?.[allowInsecureRequests] !== true);\n const headers = prepareHeaders(options?.headers);\n headers.set('accept', 'application/json');\n headers.set('content-type', 'application/json');\n const method = 'POST';\n if (options?.DPoP) {\n assertDPoP(options.DPoP);\n await options.DPoP.addProof(url, headers, method, options.initialAccessToken);\n }\n if (options?.initialAccessToken) {\n headers.set('authorization', `${headers.has('dpop') ? 'DPoP' : 'Bearer'} ${options.initialAccessToken}`);\n }\n const response = await (options?.[customFetch] || fetch)(url.href, {\n body: JSON.stringify(metadata),\n headers: Object.fromEntries(headers.entries()),\n method,\n redirect: 'manual',\n signal: signal(url, options?.signal),\n });\n options?.DPoP?.cacheNonce(response, url);\n return response;\n}\nexport async function processDynamicClientRegistrationResponse(response) {\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n await checkOAuthBodyError(response, 201, 'Dynamic Client Registration Endpoint');\n assertReadableResponse(response);\n const json = await getResponseJsonBody(response);\n assertString(json.client_id, '\"response\" body \"client_id\" property', INVALID_RESPONSE, {\n body: json,\n });\n if (json.client_secret !== undefined) {\n assertString(json.client_secret, '\"response\" body \"client_secret\" property', INVALID_RESPONSE, {\n body: json,\n });\n }\n if (json.client_secret) {\n assertNumber(json.client_secret_expires_at, true, '\"response\" body \"client_secret_expires_at\" property', INVALID_RESPONSE, {\n body: json,\n });\n }\n return json;\n}\nexport async function resourceDiscoveryRequest(resourceIdentifier, options) {\n return performDiscovery(resourceIdentifier, 'resourceIdentifier', (url) => {\n prependWellKnown(url, '.well-known/oauth-protected-resource', true);\n return url;\n }, options);\n}\nexport async function processResourceDiscoveryResponse(expectedResourceIdentifier, response) {\n const expected = expectedResourceIdentifier;\n if (!(expected instanceof URL) && expected !== _nodiscoverycheck) {\n throw CodedTypeError('\"expectedResourceIdentifier\" must be an instance of URL', ERR_INVALID_ARG_TYPE);\n }\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n if (response.status !== 200) {\n throw OPE('\"response\" is not a conform Resource Server Metadata response (unexpected HTTP status code)', RESPONSE_IS_NOT_CONFORM, response);\n }\n assertReadableResponse(response);\n const json = await getResponseJsonBody(response);\n assertString(json.resource, '\"response\" body \"resource\" property', INVALID_RESPONSE, {\n body: json,\n });\n if (expected !== _nodiscoverycheck && new URL(json.resource).href !== expected.href) {\n throw OPE('\"response\" body \"resource\" property does not match the expected value', JSON_ATTRIBUTE_COMPARISON, { expected: expected.href, body: json, attribute: 'resource' });\n }\n return json;\n}\nasync function getResponseJsonBody(response, check = assertApplicationJson) {\n let json;\n try {\n json = await response.json();\n }\n catch (cause) {\n check(response);\n throw OPE('failed to parse \"response\" body as JSON', PARSE_ERROR, cause);\n }\n if (!isJsonObject(json)) {\n throw OPE('\"response\" body must be a top level object', INVALID_RESPONSE, { body: json });\n }\n return json;\n}\nexport const _nopkce = nopkce;\nexport const _nodiscoverycheck = Symbol();\nexport const _expectedIssuer = Symbol();\n//# sourceMappingURL=index.js.map","import * as oauth from 'oauth4webapi';\nimport { compactDecrypt } from 'jose/jwe/compact/decrypt';\nimport { JOSEError } from 'jose/errors';\nlet headers;\nlet USER_AGENT;\nif (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {\n const NAME = 'openid-client';\n const VERSION = 'v6.8.1';\n USER_AGENT = `${NAME}/${VERSION}`;\n headers = { 'user-agent': USER_AGENT };\n}\nconst int = (config) => {\n return props.get(config);\n};\nlet props;\nexport { AuthorizationResponseError, ResponseBodyError, WWWAuthenticateChallengeError, } from 'oauth4webapi';\nlet tbi;\nexport function ClientSecretPost(clientSecret) {\n if (clientSecret !== undefined) {\n return oauth.ClientSecretPost(clientSecret);\n }\n tbi ||= new WeakMap();\n return (as, client, body, headers) => {\n let auth;\n if (!(auth = tbi.get(client))) {\n assertString(client.client_secret, '\"metadata.client_secret\"');\n auth = oauth.ClientSecretPost(client.client_secret);\n tbi.set(client, auth);\n }\n return auth(as, client, body, headers);\n };\n}\nfunction assertString(input, it) {\n if (typeof input !== 'string') {\n throw CodedTypeError(`${it} must be a string`, ERR_INVALID_ARG_TYPE);\n }\n if (input.length === 0) {\n throw CodedTypeError(`${it} must not be empty`, ERR_INVALID_ARG_VALUE);\n }\n}\nexport function ClientSecretBasic(clientSecret) {\n if (clientSecret !== undefined) {\n return oauth.ClientSecretBasic(clientSecret);\n }\n tbi ||= new WeakMap();\n return (as, client, body, headers) => {\n let auth;\n if (!(auth = tbi.get(client))) {\n assertString(client.client_secret, '\"metadata.client_secret\"');\n auth = oauth.ClientSecretBasic(client.client_secret);\n tbi.set(client, auth);\n }\n return auth(as, client, body, headers);\n };\n}\nexport function ClientSecretJwt(clientSecret, options) {\n if (clientSecret !== undefined) {\n return oauth.ClientSecretJwt(clientSecret, options);\n }\n tbi ||= new WeakMap();\n return (as, client, body, headers) => {\n let auth;\n if (!(auth = tbi.get(client))) {\n assertString(client.client_secret, '\"metadata.client_secret\"');\n auth = oauth.ClientSecretJwt(client.client_secret, options);\n tbi.set(client, auth);\n }\n return auth(as, client, body, headers);\n };\n}\nexport function None() {\n return oauth.None();\n}\nexport function PrivateKeyJwt(clientPrivateKey, options) {\n return oauth.PrivateKeyJwt(clientPrivateKey, options);\n}\nexport function TlsClientAuth() {\n return oauth.TlsClientAuth();\n}\nexport const skipStateCheck = oauth.skipStateCheck;\nexport const skipSubjectCheck = oauth.skipSubjectCheck;\nexport const customFetch = oauth.customFetch;\nexport const modifyAssertion = oauth.modifyAssertion;\nexport const clockSkew = oauth.clockSkew;\nexport const clockTolerance = oauth.clockTolerance;\nconst ERR_INVALID_ARG_VALUE = 'ERR_INVALID_ARG_VALUE';\nconst ERR_INVALID_ARG_TYPE = 'ERR_INVALID_ARG_TYPE';\nfunction CodedTypeError(message, code, cause) {\n const err = new TypeError(message, { cause });\n Object.assign(err, { code });\n return err;\n}\nexport function calculatePKCECodeChallenge(codeVerifier) {\n return oauth.calculatePKCECodeChallenge(codeVerifier);\n}\nexport function randomPKCECodeVerifier() {\n return oauth.generateRandomCodeVerifier();\n}\nexport function randomNonce() {\n return oauth.generateRandomNonce();\n}\nexport function randomState() {\n return oauth.generateRandomState();\n}\nexport class ClientError extends Error {\n code;\n constructor(message, options) {\n super(message, options);\n this.name = this.constructor.name;\n this.code = options?.code;\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nconst decoder = new TextDecoder();\nfunction e(msg, cause, code) {\n return new ClientError(msg, { cause, code });\n}\nfunction errorHandler(err) {\n if (err instanceof TypeError ||\n err instanceof ClientError ||\n err instanceof oauth.ResponseBodyError ||\n err instanceof oauth.AuthorizationResponseError ||\n err instanceof oauth.WWWAuthenticateChallengeError) {\n throw err;\n }\n if (err instanceof oauth.OperationProcessingError) {\n switch (err.code) {\n case oauth.HTTP_REQUEST_FORBIDDEN:\n throw e('only requests to HTTPS are allowed', err, err.code);\n case oauth.REQUEST_PROTOCOL_FORBIDDEN:\n throw e('only requests to HTTP or HTTPS are allowed', err, err.code);\n case oauth.RESPONSE_IS_NOT_CONFORM:\n throw e('unexpected HTTP response status code', err.cause, err.code);\n case oauth.RESPONSE_IS_NOT_JSON:\n throw e('unexpected response content-type', err.cause, err.code);\n case oauth.PARSE_ERROR:\n throw e('parsing error occured', err, err.code);\n case oauth.INVALID_RESPONSE:\n throw e('invalid response encountered', err, err.code);\n case oauth.JWT_CLAIM_COMPARISON:\n throw e('unexpected JWT claim value encountered', err, err.code);\n case oauth.JSON_ATTRIBUTE_COMPARISON:\n throw e('unexpected JSON attribute value encountered', err, err.code);\n case oauth.JWT_TIMESTAMP_CHECK:\n throw e('JWT timestamp claim value failed validation', err, err.code);\n default:\n throw e(err.message, err, err.code);\n }\n }\n if (err instanceof oauth.UnsupportedOperationError) {\n throw e('unsupported operation', err, err.code);\n }\n if (err instanceof DOMException) {\n switch (err.name) {\n case 'OperationError':\n throw e('runtime operation error', err, oauth.UNSUPPORTED_OPERATION);\n case 'NotSupportedError':\n throw e('runtime unsupported operation', err, oauth.UNSUPPORTED_OPERATION);\n case 'TimeoutError':\n throw e('operation timed out', err, 'OAUTH_TIMEOUT');\n case 'AbortError':\n throw e('operation aborted', err, 'OAUTH_ABORT');\n }\n }\n throw new ClientError('something went wrong', { cause: err });\n}\nexport function randomDPoPKeyPair(alg, options) {\n return oauth\n .generateKeyPair(alg ?? 'ES256', {\n extractable: options?.extractable,\n })\n .catch(errorHandler);\n}\nfunction handleEntraId(server, as, options) {\n if (server.origin === 'https://login.microsoftonline.com' &&\n (!options?.algorithm || options.algorithm === 'oidc')) {\n as[kEntraId] = true;\n return true;\n }\n return false;\n}\nfunction handleB2Clogin(server, options) {\n if (server.hostname.endsWith('.b2clogin.com') &&\n (!options?.algorithm || options.algorithm === 'oidc')) {\n return true;\n }\n return false;\n}\nexport async function dynamicClientRegistration(server, metadata, clientAuthentication, options) {\n let as;\n if (options?.flag === retry) {\n as = options.as;\n }\n else {\n as = await performDiscovery(server, options);\n }\n const clockSkew = metadata[oauth.clockSkew] ?? 0;\n const clockTolerance = metadata[oauth.clockTolerance] ?? 30;\n metadata = structuredClone(metadata);\n const timeout = options?.timeout ?? 30;\n const signal = AbortSignal.timeout(timeout * 1000);\n let registered;\n try {\n registered = await oauth\n .dynamicClientRegistrationRequest(as, metadata, {\n initialAccessToken: options?.initialAccessToken,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n [oauth.customFetch]: options?.[customFetch],\n [oauth.allowInsecureRequests]: options?.execute?.includes(allowInsecureRequests),\n signal,\n })\n .then(oauth.processDynamicClientRegistrationResponse);\n }\n catch (err) {\n if (retryable(err, options)) {\n return dynamicClientRegistration(server, metadata, clientAuthentication, {\n ...options,\n flag: retry,\n as,\n });\n }\n errorHandler(err);\n }\n registered[oauth.clockSkew] = clockSkew;\n registered[oauth.clockTolerance] = clockTolerance;\n const instance = new Configuration(as, registered.client_id, registered, clientAuthentication);\n let internals = int(instance);\n if (options?.[customFetch]) {\n internals.fetch = options[customFetch];\n }\n if (options?.timeout) {\n internals.timeout = options.timeout;\n }\n if (options?.execute) {\n for (const extension of options.execute) {\n extension(instance);\n }\n }\n return instance;\n}\nexport async function discovery(server, clientId, metadata, clientAuthentication, options) {\n const as = await performDiscovery(server, options);\n const instance = new Configuration(as, clientId, metadata, clientAuthentication);\n let internals = int(instance);\n if (options?.[customFetch]) {\n internals.fetch = options[customFetch];\n }\n if (options?.timeout) {\n internals.timeout = options.timeout;\n }\n if (options?.execute) {\n for (const extension of options.execute) {\n extension(instance);\n }\n }\n return instance;\n}\nasync function performDiscovery(server, options) {\n if (!(server instanceof URL)) {\n throw CodedTypeError('\"server\" must be an instance of URL', ERR_INVALID_ARG_TYPE);\n }\n const resolve = !server.href.includes('/.well-known/');\n const timeout = options?.timeout ?? 30;\n const signal = AbortSignal.timeout(timeout * 1000);\n const as = await (resolve\n ? oauth.discoveryRequest(server, {\n algorithm: options?.algorithm,\n [oauth.customFetch]: options?.[customFetch],\n [oauth.allowInsecureRequests]: options?.execute?.includes(allowInsecureRequests),\n signal,\n headers: new Headers(headers),\n })\n : (options?.[customFetch] || fetch)((() => {\n oauth.checkProtocol(server, options?.execute?.includes(allowInsecureRequests) ? false : true);\n return server.href;\n })(), {\n headers: Object.fromEntries(new Headers({ accept: 'application/json', ...headers }).entries()),\n body: undefined,\n method: 'GET',\n redirect: 'manual',\n signal,\n }))\n .then((response) => oauth.processDiscoveryResponse(oauth._nodiscoverycheck, response))\n .catch(errorHandler);\n if (resolve && new URL(as.issuer).href !== server.href) {\n handleEntraId(server, as, options) ||\n handleB2Clogin(server, options) ||\n (() => {\n throw new ClientError('discovered metadata issuer does not match the expected issuer', {\n code: oauth.JSON_ATTRIBUTE_COMPARISON,\n cause: {\n expected: server.href,\n body: as,\n attribute: 'issuer',\n },\n });\n })();\n }\n return as;\n}\nfunction isRsaOaep(input) {\n return input.name === 'RSA-OAEP';\n}\nfunction isEcdh(input) {\n return input.name === 'ECDH';\n}\nconst ecdhEs = 'ECDH-ES';\nconst ecdhEsA128Kw = 'ECDH-ES+A128KW';\nconst ecdhEsA192Kw = 'ECDH-ES+A192KW';\nconst ecdhEsA256Kw = 'ECDH-ES+A256KW';\nfunction checkEcdhAlg(algs, alg, pk) {\n switch (alg) {\n case undefined:\n algs.add(ecdhEs);\n algs.add(ecdhEsA128Kw);\n algs.add(ecdhEsA192Kw);\n algs.add(ecdhEsA256Kw);\n break;\n case ecdhEs:\n case ecdhEsA128Kw:\n case ecdhEsA192Kw:\n case ecdhEsA256Kw:\n algs.add(alg);\n break;\n default:\n throw CodedTypeError('invalid key alg', ERR_INVALID_ARG_VALUE, { pk });\n }\n}\nexport function enableDecryptingResponses(config, contentEncryptionAlgorithms = [\n 'A128GCM',\n 'A192GCM',\n 'A256GCM',\n 'A128CBC-HS256',\n 'A192CBC-HS384',\n 'A256CBC-HS512',\n], ...keys) {\n if (int(config).decrypt !== undefined) {\n throw new TypeError('enableDecryptingResponses can only be called on a given Configuration instance once');\n }\n if (keys.length === 0) {\n throw CodedTypeError('no keys were provided', ERR_INVALID_ARG_VALUE);\n }\n const algs = new Set();\n const normalized = [];\n for (const pk of keys) {\n let key;\n if ('key' in pk) {\n key = { key: pk.key };\n if (typeof pk.alg === 'string')\n key.alg = pk.alg;\n if (typeof pk.kid === 'string')\n key.kid = pk.kid;\n }\n else {\n key = { key: pk };\n }\n if (key.key.type !== 'private') {\n throw CodedTypeError('only private keys must be provided', ERR_INVALID_ARG_VALUE);\n }\n if (isRsaOaep(key.key.algorithm)) {\n switch (key.key.algorithm.hash.name) {\n case 'SHA-1':\n case 'SHA-256':\n case 'SHA-384':\n case 'SHA-512': {\n let alg = 'RSA-OAEP';\n let sha;\n if ((sha = parseInt(key.key.algorithm.hash.name.slice(-3), 10))) {\n alg = `${alg}-${sha}`;\n }\n key.alg ||= alg;\n if (alg !== key.alg)\n throw CodedTypeError('invalid key alg', ERR_INVALID_ARG_VALUE, {\n pk,\n });\n algs.add(key.alg);\n break;\n }\n default:\n throw CodedTypeError('only SHA-512, SHA-384, SHA-256, and SHA-1 RSA-OAEP keys are supported', ERR_INVALID_ARG_VALUE);\n }\n }\n else if (isEcdh(key.key.algorithm)) {\n if (key.key.algorithm.namedCurve !== 'P-256') {\n throw CodedTypeError('Only P-256 ECDH keys are supported', ERR_INVALID_ARG_VALUE);\n }\n checkEcdhAlg(algs, key.alg, pk);\n }\n else if (key.key.algorithm.name === 'X25519') {\n checkEcdhAlg(algs, key.alg, pk);\n }\n else {\n throw CodedTypeError('only RSA-OAEP, ECDH, or X25519 keys are supported', ERR_INVALID_ARG_VALUE);\n }\n normalized.push(key);\n }\n int(config).decrypt = async (jwe) => decrypt(normalized, jwe, contentEncryptionAlgorithms, [...algs]).catch(errorHandler);\n}\nfunction checkCryptoKey(key, alg, epk) {\n if (alg.startsWith('RSA-OAEP')) {\n return true;\n }\n if (alg.startsWith('ECDH-ES')) {\n if (key.algorithm.name !== 'ECDH' && key.algorithm.name !== 'X25519') {\n return false;\n }\n if (key.algorithm.name === 'ECDH') {\n return epk?.crv === key.algorithm.namedCurve;\n }\n if (key.algorithm.name === 'X25519') {\n return epk?.crv === 'X25519';\n }\n }\n return false;\n}\nfunction selectCryptoKeyForDecryption(keys, alg, kid, epk) {\n const { 0: key, length } = keys.filter((key) => {\n if (kid !== key.kid) {\n return false;\n }\n if (key.alg && alg !== key.alg) {\n return false;\n }\n return checkCryptoKey(key.key, alg, epk);\n });\n if (!key) {\n throw e('no applicable decryption key selected', undefined, 'OAUTH_DECRYPTION_FAILED');\n }\n if (length !== 1) {\n throw e('multiple applicable decryption keys selected', undefined, 'OAUTH_DECRYPTION_FAILED');\n }\n return key.key;\n}\nasync function decrypt(keys, jwe, contentEncryptionAlgorithms, keyManagementAlgorithms) {\n return decoder.decode((await compactDecrypt(jwe, (header) => {\n const { kid, alg, epk } = header;\n return selectCryptoKeyForDecryption(keys, alg, kid, epk);\n }, { keyManagementAlgorithms, contentEncryptionAlgorithms }).catch((err) => {\n if (err instanceof JOSEError) {\n throw e('decryption failed', err, 'OAUTH_DECRYPTION_FAILED');\n }\n errorHandler(err);\n })).plaintext);\n}\nfunction getServerHelpers(metadata) {\n return {\n supportsPKCE: {\n __proto__: null,\n value(method = 'S256') {\n return (metadata.code_challenge_methods_supported?.includes(method) === true);\n },\n },\n };\n}\nfunction addServerHelpers(metadata) {\n Object.defineProperties(metadata, getServerHelpers(metadata));\n}\nconst kEntraId = Symbol();\nexport class Configuration {\n constructor(server, clientId, metadata, clientAuthentication) {\n if (typeof clientId !== 'string' || !clientId.length) {\n throw CodedTypeError('\"clientId\" must be a non-empty string', ERR_INVALID_ARG_TYPE);\n }\n if (typeof metadata === 'string') {\n metadata = { client_secret: metadata };\n }\n if (metadata?.client_id !== undefined && clientId !== metadata.client_id) {\n throw CodedTypeError('\"clientId\" and \"metadata.client_id\" must be the same', ERR_INVALID_ARG_VALUE);\n }\n const client = {\n ...structuredClone(metadata),\n client_id: clientId,\n };\n client[oauth.clockSkew] = metadata?.[oauth.clockSkew] ?? 0;\n client[oauth.clockTolerance] = metadata?.[oauth.clockTolerance] ?? 30;\n let auth;\n if (clientAuthentication) {\n auth = clientAuthentication;\n }\n else {\n if (typeof client.client_secret === 'string' &&\n client.client_secret.length) {\n auth = ClientSecretPost(client.client_secret);\n }\n else {\n auth = None();\n }\n }\n let c = Object.freeze(client);\n const clone = structuredClone(server);\n if (kEntraId in server) {\n clone[oauth._expectedIssuer] = ({ claims: { tid } }) => server.issuer.replace('{tenantid}', tid);\n }\n let as = Object.freeze(clone);\n props ||= new WeakMap();\n props.set(this, {\n __proto__: null,\n as,\n c,\n auth,\n tlsOnly: true,\n jwksCache: {},\n });\n }\n serverMetadata() {\n const metadata = structuredClone(int(this).as);\n addServerHelpers(metadata);\n return metadata;\n }\n clientMetadata() {\n const metadata = structuredClone(int(this).c);\n return metadata;\n }\n get timeout() {\n return int(this).timeout;\n }\n set timeout(value) {\n int(this).timeout = value;\n }\n get [customFetch]() {\n return int(this).fetch;\n }\n set [customFetch](value) {\n int(this).fetch = value;\n }\n}\nObject.freeze(Configuration.prototype);\nfunction getHelpers(response) {\n let exp = undefined;\n if (response.expires_in !== undefined) {\n const now = new Date();\n now.setSeconds(now.getSeconds() + response.expires_in);\n exp = now.getTime();\n }\n return {\n expiresIn: {\n __proto__: null,\n value() {\n if (exp) {\n const now = Date.now();\n if (exp > now) {\n return Math.floor((exp - now) / 1000);\n }\n return 0;\n }\n return undefined;\n },\n },\n claims: {\n __proto__: null,\n value() {\n try {\n return oauth.getValidatedIdTokenClaims(this);\n }\n catch {\n return undefined;\n }\n },\n },\n };\n}\nfunction addHelpers(response) {\n Object.defineProperties(response, getHelpers(response));\n}\nexport function getDPoPHandle(config, keyPair, options) {\n checkConfig(config);\n return oauth.DPoP(int(config).c, keyPair, options);\n}\nasync function handleRetryAfter(response, currentInterval, signal, throwIfInvalid = false) {\n const retryAfter = response.headers.get('retry-after')?.trim();\n if (retryAfter === undefined)\n return;\n let delaySeconds;\n if (/^\\d+$/.test(retryAfter)) {\n delaySeconds = parseInt(retryAfter, 10);\n }\n else {\n const retryDate = new Date(retryAfter);\n if (Number.isFinite(retryDate.getTime())) {\n const now = new Date();\n const delayMs = retryDate.getTime() - now.getTime();\n if (delayMs > 0) {\n delaySeconds = Math.ceil(delayMs / 1000);\n }\n }\n }\n if (throwIfInvalid && !Number.isFinite(delaySeconds)) {\n throw new oauth.OperationProcessingError('invalid Retry-After header value', { cause: response });\n }\n if (delaySeconds > currentInterval) {\n await wait(delaySeconds - currentInterval, signal);\n }\n}\nfunction wait(duration, signal) {\n return new Promise((resolve, reject) => {\n const waitStep = (remaining) => {\n try {\n signal.throwIfAborted();\n }\n catch (err) {\n reject(err);\n return;\n }\n if (remaining <= 0) {\n resolve();\n return;\n }\n const currentWait = Math.min(remaining, 5);\n setTimeout(() => waitStep(remaining - currentWait), currentWait * 1000);\n };\n waitStep(duration);\n });\n}\nexport async function pollDeviceAuthorizationGrant(config, deviceAuthorizationResponse, parameters, options) {\n checkConfig(config);\n parameters = new URLSearchParams(parameters);\n let interval = deviceAuthorizationResponse.interval ?? 5;\n const pollingSignal = options?.signal ??\n AbortSignal.timeout(deviceAuthorizationResponse.expires_in * 1000);\n try {\n await wait(interval, pollingSignal);\n }\n catch (err) {\n errorHandler(err);\n }\n const { as, c, auth, fetch, tlsOnly, nonRepudiation, timeout, decrypt } = int(config);\n const retryPoll = (updatedInterval, flag) => pollDeviceAuthorizationGrant(config, {\n ...deviceAuthorizationResponse,\n interval: updatedInterval,\n }, parameters, {\n ...options,\n signal: pollingSignal,\n flag,\n });\n const response = await oauth\n .deviceCodeGrantRequest(as, c, auth, deviceAuthorizationResponse.device_code, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n additionalParameters: parameters,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n signal: pollingSignal.aborted ? pollingSignal : signal(timeout),\n })\n .catch(errorHandler);\n if (response.status === 503 && response.headers.has('retry-after')) {\n await handleRetryAfter(response, interval, pollingSignal, true);\n await response.body?.cancel();\n return retryPoll(interval);\n }\n const p = oauth.processDeviceCodeResponse(as, c, response, {\n [oauth.jweDecrypt]: decrypt,\n });\n let result;\n try {\n result = await p;\n }\n catch (err) {\n if (retryable(err, options)) {\n return retryPoll(interval, retry);\n }\n if (err instanceof oauth.ResponseBodyError) {\n switch (err.error) {\n case 'slow_down':\n interval += 5;\n case 'authorization_pending':\n await handleRetryAfter(err.response, interval, pollingSignal);\n return retryPoll(interval);\n }\n }\n errorHandler(err);\n }\n result.id_token && (await nonRepudiation?.(response));\n addHelpers(result);\n return result;\n}\nexport async function initiateDeviceAuthorization(config, parameters) {\n checkConfig(config);\n const { as, c, auth, fetch, tlsOnly, timeout } = int(config);\n return oauth\n .deviceAuthorizationRequest(as, c, auth, parameters, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .then((response) => oauth.processDeviceAuthorizationResponse(as, c, response))\n .catch(errorHandler);\n}\nexport async function initiateBackchannelAuthentication(config, parameters) {\n checkConfig(config);\n const { as, c, auth, fetch, tlsOnly, timeout } = int(config);\n return oauth\n .backchannelAuthenticationRequest(as, c, auth, parameters, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .then((response) => oauth.processBackchannelAuthenticationResponse(as, c, response))\n .catch(errorHandler);\n}\nexport async function pollBackchannelAuthenticationGrant(config, backchannelAuthenticationResponse, parameters, options) {\n checkConfig(config);\n parameters = new URLSearchParams(parameters);\n let interval = backchannelAuthenticationResponse.interval ?? 5;\n const pollingSignal = options?.signal ??\n AbortSignal.timeout(backchannelAuthenticationResponse.expires_in * 1000);\n try {\n await wait(interval, pollingSignal);\n }\n catch (err) {\n errorHandler(err);\n }\n const { as, c, auth, fetch, tlsOnly, nonRepudiation, timeout, decrypt } = int(config);\n const retryPoll = (updatedInterval, flag) => pollBackchannelAuthenticationGrant(config, {\n ...backchannelAuthenticationResponse,\n interval: updatedInterval,\n }, parameters, {\n ...options,\n signal: pollingSignal,\n flag,\n });\n const response = await oauth\n .backchannelAuthenticationGrantRequest(as, c, auth, backchannelAuthenticationResponse.auth_req_id, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n additionalParameters: parameters,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n signal: pollingSignal.aborted ? pollingSignal : signal(timeout),\n })\n .catch(errorHandler);\n if (response.status === 503 && response.headers.has('retry-after')) {\n await handleRetryAfter(response, interval, pollingSignal, true);\n await response.body?.cancel();\n return retryPoll(interval);\n }\n const p = oauth.processBackchannelAuthenticationGrantResponse(as, c, response, {\n [oauth.jweDecrypt]: decrypt,\n });\n let result;\n try {\n result = await p;\n }\n catch (err) {\n if (retryable(err, options)) {\n return retryPoll(interval, retry);\n }\n if (err instanceof oauth.ResponseBodyError) {\n switch (err.error) {\n case 'slow_down':\n interval += 5;\n case 'authorization_pending':\n await handleRetryAfter(err.response, interval, pollingSignal);\n return retryPoll(interval);\n }\n }\n errorHandler(err);\n }\n result.id_token && (await nonRepudiation?.(response));\n addHelpers(result);\n return result;\n}\nexport function allowInsecureRequests(config) {\n int(config).tlsOnly = false;\n}\nexport function setJwksCache(config, jwksCache) {\n int(config).jwksCache = structuredClone(jwksCache);\n}\nexport function getJwksCache(config) {\n const cache = int(config).jwksCache;\n if (cache.uat) {\n return cache;\n }\n return undefined;\n}\nexport function enableNonRepudiationChecks(config) {\n checkConfig(config);\n int(config).nonRepudiation = (response) => {\n const { as, fetch, tlsOnly, timeout, jwksCache } = int(config);\n return oauth\n .validateApplicationLevelSignature(as, response, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n headers: new Headers(headers),\n signal: signal(timeout),\n [oauth.jwksCache]: jwksCache,\n })\n .catch(errorHandler);\n };\n}\nexport function useJwtResponseMode(config) {\n checkConfig(config);\n const { hybrid, implicit } = int(config);\n if (hybrid || implicit) {\n throw e('JARM cannot be combined with a hybrid or implicit response types', undefined, oauth.UNSUPPORTED_OPERATION);\n }\n int(config).jarm = (authorizationResponse, expectedState) => validateJARMResponse(config, authorizationResponse, expectedState);\n}\nexport function enableDetachedSignatureResponseChecks(config) {\n if (!int(config).hybrid) {\n throw e('\"code id_token\" response type must be configured to be used first', undefined, oauth.UNSUPPORTED_OPERATION);\n }\n int(config).hybrid = (authorizationResponse, expectedNonce, expectedState, maxAge) => validateCodeIdTokenResponse(config, authorizationResponse, expectedNonce, expectedState, maxAge, true);\n}\nexport async function implicitAuthentication(config, currentUrl, expectedNonce, checks) {\n checkConfig(config);\n if (!(currentUrl instanceof URL) &&\n !webInstanceOf(currentUrl, 'Request')) {\n throw CodedTypeError('\"currentUrl\" must be an instance of URL, or Request', ERR_INVALID_ARG_TYPE);\n }\n if (typeof expectedNonce !== 'string') {\n throw CodedTypeError('\"expectedNonce\" must be a string', ERR_INVALID_ARG_TYPE);\n }\n const { as, c, fetch, tlsOnly, timeout, decrypt, implicit, jwksCache } = int(config);\n if (!implicit) {\n throw new TypeError('implicitAuthentication() cannot be used by clients using flows other than response_type=id_token');\n }\n let params;\n if (!(currentUrl instanceof URL)) {\n const request = currentUrl;\n switch (request.method) {\n case 'GET':\n params = new URLSearchParams(new URL(request.url).hash.slice(1));\n break;\n case 'POST':\n params = new URLSearchParams(await oauth.formPostResponse(request));\n break;\n default:\n throw CodedTypeError('unexpected Request HTTP method', ERR_INVALID_ARG_VALUE);\n }\n }\n else {\n params = new URLSearchParams(currentUrl.hash.slice(1));\n }\n try {\n {\n const decoy = new URLSearchParams(params);\n decoy.delete('id_token');\n oauth.validateAuthResponse({\n ...as,\n authorization_response_iss_parameter_supported: undefined,\n }, c, decoy, checks?.expectedState);\n }\n {\n const decoy = new Response(JSON.stringify({\n access_token: 'decoy',\n token_type: 'bearer',\n id_token: params.get('id_token'),\n }), {\n headers: new Headers({ 'content-type': 'application/json' }),\n });\n const ref = await oauth.processAuthorizationCodeResponse(as, c, decoy, {\n expectedNonce,\n maxAge: checks?.maxAge,\n [oauth.jweDecrypt]: decrypt,\n });\n await oauth.validateApplicationLevelSignature(as, decoy, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n headers: new Headers(headers),\n signal: signal(timeout),\n [oauth.jwksCache]: jwksCache,\n });\n return oauth.getValidatedIdTokenClaims(ref);\n }\n }\n catch (err) {\n errorHandler(err);\n }\n}\nexport function useCodeIdTokenResponseType(config) {\n checkConfig(config);\n const { jarm, implicit } = int(config);\n if (jarm || implicit) {\n throw e('\"code id_token\" response type cannot be combined with JARM or implicit response type', undefined, oauth.UNSUPPORTED_OPERATION);\n }\n int(config).hybrid = (authorizationResponse, expectedNonce, expectedState, maxAge) => validateCodeIdTokenResponse(config, authorizationResponse, expectedNonce, expectedState, maxAge, false);\n}\nexport function useIdTokenResponseType(config) {\n checkConfig(config);\n const { jarm, hybrid } = int(config);\n if (jarm || hybrid) {\n throw e('\"id_token\" response type cannot be combined with JARM or hybrid response type', undefined, oauth.UNSUPPORTED_OPERATION);\n }\n int(config).implicit = true;\n}\nfunction stripParams(url) {\n url = new URL(url);\n url.search = '';\n url.hash = '';\n return url.href;\n}\nfunction webInstanceOf(input, toStringTag) {\n try {\n return Object.getPrototypeOf(input)[Symbol.toStringTag] === toStringTag;\n }\n catch {\n return false;\n }\n}\nexport async function authorizationCodeGrant(config, currentUrl, checks, tokenEndpointParameters, options) {\n checkConfig(config);\n if (options?.flag !== retry &&\n !(currentUrl instanceof URL) &&\n !webInstanceOf(currentUrl, 'Request')) {\n throw CodedTypeError('\"currentUrl\" must be an instance of URL, or Request', ERR_INVALID_ARG_TYPE);\n }\n let authResponse;\n let redirectUri;\n const { as, c, auth, fetch, tlsOnly, jarm, hybrid, nonRepudiation, timeout, decrypt, implicit } = int(config);\n if (options?.flag === retry) {\n authResponse = options.authResponse;\n redirectUri = options.redirectUri;\n }\n else {\n if (!(currentUrl instanceof URL)) {\n const request = currentUrl;\n currentUrl = new URL(currentUrl.url);\n switch (request.method) {\n case 'GET':\n break;\n case 'POST':\n const params = new URLSearchParams(await oauth.formPostResponse(request));\n if (hybrid) {\n currentUrl.hash = params.toString();\n }\n else {\n for (const [k, v] of params.entries()) {\n currentUrl.searchParams.append(k, v);\n }\n }\n break;\n default:\n throw CodedTypeError('unexpected Request HTTP method', ERR_INVALID_ARG_VALUE);\n }\n }\n redirectUri = stripParams(currentUrl);\n switch (true) {\n case !!jarm:\n authResponse = await jarm(currentUrl, checks?.expectedState);\n break;\n case !!hybrid:\n authResponse = await hybrid(currentUrl, checks?.expectedNonce, checks?.expectedState, checks?.maxAge);\n break;\n case !!implicit:\n throw new TypeError('authorizationCodeGrant() cannot be used by response_type=id_token clients');\n default:\n try {\n authResponse = oauth.validateAuthResponse(as, c, currentUrl.searchParams, checks?.expectedState);\n }\n catch (err) {\n errorHandler(err);\n }\n }\n }\n const response = await oauth\n .authorizationCodeGrantRequest(as, c, auth, authResponse, redirectUri, checks?.pkceCodeVerifier || oauth.nopkce, {\n additionalParameters: tokenEndpointParameters,\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .catch(errorHandler);\n if (typeof checks?.expectedNonce === 'string' ||\n typeof checks?.maxAge === 'number') {\n checks.idTokenExpected = true;\n }\n const p = oauth.processAuthorizationCodeResponse(as, c, response, {\n expectedNonce: checks?.expectedNonce,\n maxAge: checks?.maxAge,\n requireIdToken: checks?.idTokenExpected,\n [oauth.jweDecrypt]: decrypt,\n });\n let result;\n try {\n result = await p;\n }\n catch (err) {\n if (retryable(err, options)) {\n return authorizationCodeGrant(config, undefined, checks, tokenEndpointParameters, {\n ...options,\n flag: retry,\n authResponse: authResponse,\n redirectUri: redirectUri,\n });\n }\n errorHandler(err);\n }\n result.id_token && (await nonRepudiation?.(response));\n addHelpers(result);\n return result;\n}\nasync function validateJARMResponse(config, authorizationResponse, expectedState) {\n const { as, c, fetch, tlsOnly, timeout, decrypt, jwksCache } = int(config);\n return oauth\n .validateJwtAuthResponse(as, c, authorizationResponse, expectedState, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n headers: new Headers(headers),\n signal: signal(timeout),\n [oauth.jweDecrypt]: decrypt,\n [oauth.jwksCache]: jwksCache,\n })\n .catch(errorHandler);\n}\nasync function validateCodeIdTokenResponse(config, authorizationResponse, expectedNonce, expectedState, maxAge, fapi) {\n if (typeof expectedNonce !== 'string') {\n throw CodedTypeError('\"expectedNonce\" must be a string', ERR_INVALID_ARG_TYPE);\n }\n if (expectedState !== undefined && typeof expectedState !== 'string') {\n throw CodedTypeError('\"expectedState\" must be a string', ERR_INVALID_ARG_TYPE);\n }\n const { as, c, fetch, tlsOnly, timeout, decrypt, jwksCache } = int(config);\n return (fapi\n ? oauth.validateDetachedSignatureResponse\n : oauth.validateCodeIdTokenResponse)(as, c, authorizationResponse, expectedNonce, expectedState, maxAge, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n headers: new Headers(headers),\n signal: signal(timeout),\n [oauth.jweDecrypt]: decrypt,\n [oauth.jwksCache]: jwksCache,\n }).catch(errorHandler);\n}\nexport async function refreshTokenGrant(config, refreshToken, parameters, options) {\n checkConfig(config);\n parameters = new URLSearchParams(parameters);\n const { as, c, auth, fetch, tlsOnly, nonRepudiation, timeout, decrypt } = int(config);\n const response = await oauth\n .refreshTokenGrantRequest(as, c, auth, refreshToken, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n additionalParameters: parameters,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .catch(errorHandler);\n const p = oauth.processRefreshTokenResponse(as, c, response, {\n [oauth.jweDecrypt]: decrypt,\n });\n let result;\n try {\n result = await p;\n }\n catch (err) {\n if (retryable(err, options)) {\n return refreshTokenGrant(config, refreshToken, parameters, {\n ...options,\n flag: retry,\n });\n }\n errorHandler(err);\n }\n result.id_token && (await nonRepudiation?.(response));\n addHelpers(result);\n return result;\n}\nexport async function clientCredentialsGrant(config, parameters, options) {\n checkConfig(config);\n parameters = new URLSearchParams(parameters);\n const { as, c, auth, fetch, tlsOnly, timeout } = int(config);\n const response = await oauth\n .clientCredentialsGrantRequest(as, c, auth, parameters, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .catch(errorHandler);\n const p = oauth.processClientCredentialsResponse(as, c, response);\n let result;\n try {\n result = await p;\n }\n catch (err) {\n if (retryable(err, options)) {\n return clientCredentialsGrant(config, parameters, {\n ...options,\n flag: retry,\n });\n }\n errorHandler(err);\n }\n addHelpers(result);\n return result;\n}\nexport function buildAuthorizationUrl(config, parameters) {\n checkConfig(config);\n const { as, c, tlsOnly, hybrid, jarm, implicit } = int(config);\n const authorizationEndpoint = oauth.resolveEndpoint(as, 'authorization_endpoint', false, tlsOnly);\n parameters = new URLSearchParams(parameters);\n if (!parameters.has('client_id')) {\n parameters.set('client_id', c.client_id);\n }\n if (!parameters.has('request_uri') && !parameters.has('request')) {\n if (!parameters.has('response_type')) {\n parameters.set('response_type', hybrid ? 'code id_token' : implicit ? 'id_token' : 'code');\n }\n if (implicit && !parameters.has('nonce')) {\n throw CodedTypeError('response_type=id_token clients must provide a nonce parameter in their authorization request parameters', ERR_INVALID_ARG_VALUE);\n }\n if (jarm) {\n parameters.set('response_mode', 'jwt');\n }\n }\n for (const [k, v] of parameters.entries()) {\n authorizationEndpoint.searchParams.append(k, v);\n }\n return authorizationEndpoint;\n}\nexport async function buildAuthorizationUrlWithJAR(config, parameters, signingKey, options) {\n checkConfig(config);\n const authorizationEndpoint = buildAuthorizationUrl(config, parameters);\n parameters = authorizationEndpoint.searchParams;\n if (!signingKey) {\n throw CodedTypeError('\"signingKey\" must be provided', ERR_INVALID_ARG_VALUE);\n }\n const { as, c } = int(config);\n const request = await oauth\n .issueRequestObject(as, c, parameters, signingKey, options)\n .catch(errorHandler);\n return buildAuthorizationUrl(config, { request });\n}\nexport async function buildAuthorizationUrlWithPAR(config, parameters, options) {\n checkConfig(config);\n const authorizationEndpoint = buildAuthorizationUrl(config, parameters);\n const { as, c, auth, fetch, tlsOnly, timeout } = int(config);\n const response = await oauth\n .pushedAuthorizationRequest(as, c, auth, authorizationEndpoint.searchParams, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .catch(errorHandler);\n const p = oauth.processPushedAuthorizationResponse(as, c, response);\n let result;\n try {\n result = await p;\n }\n catch (err) {\n if (retryable(err, options)) {\n return buildAuthorizationUrlWithPAR(config, parameters, {\n ...options,\n flag: retry,\n });\n }\n errorHandler(err);\n }\n return buildAuthorizationUrl(config, { request_uri: result.request_uri });\n}\nexport function buildEndSessionUrl(config, parameters) {\n checkConfig(config);\n const { as, c, tlsOnly } = int(config);\n const endSessionEndpoint = oauth.resolveEndpoint(as, 'end_session_endpoint', false, tlsOnly);\n parameters = new URLSearchParams(parameters);\n if (!parameters.has('client_id')) {\n parameters.set('client_id', c.client_id);\n }\n for (const [k, v] of parameters.entries()) {\n endSessionEndpoint.searchParams.append(k, v);\n }\n return endSessionEndpoint;\n}\nfunction checkConfig(input) {\n if (!(input instanceof Configuration)) {\n throw CodedTypeError('\"config\" must be an instance of Configuration', ERR_INVALID_ARG_TYPE);\n }\n if (Object.getPrototypeOf(input) !== Configuration.prototype) {\n throw CodedTypeError('subclassing Configuration is not allowed', ERR_INVALID_ARG_VALUE);\n }\n}\nfunction signal(timeout) {\n return timeout ? AbortSignal.timeout(timeout * 1000) : undefined;\n}\nexport async function fetchUserInfo(config, accessToken, expectedSubject, options) {\n checkConfig(config);\n const { as, c, fetch, tlsOnly, nonRepudiation, timeout, decrypt } = int(config);\n const response = await oauth\n .userInfoRequest(as, c, accessToken, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .catch(errorHandler);\n let exec = oauth.processUserInfoResponse(as, c, expectedSubject, response, {\n [oauth.jweDecrypt]: decrypt,\n });\n let result;\n try {\n result = await exec;\n }\n catch (err) {\n if (retryable(err, options)) {\n return fetchUserInfo(config, accessToken, expectedSubject, {\n ...options,\n flag: retry,\n });\n }\n errorHandler(err);\n }\n oauth.getContentType(response) === 'application/jwt' &&\n (await nonRepudiation?.(response));\n return result;\n}\nfunction retryable(err, options) {\n if (options?.DPoP && options.flag !== retry) {\n return oauth.isDPoPNonceError(err);\n }\n return false;\n}\nexport async function tokenIntrospection(config, token, parameters) {\n checkConfig(config);\n const { as, c, auth, fetch, tlsOnly, nonRepudiation, timeout, decrypt } = int(config);\n const response = await oauth\n .introspectionRequest(as, c, auth, token, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n additionalParameters: new URLSearchParams(parameters),\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .catch(errorHandler);\n const result = await oauth\n .processIntrospectionResponse(as, c, response, {\n [oauth.jweDecrypt]: decrypt,\n })\n .catch(errorHandler);\n oauth.getContentType(response) === 'application/token-introspection+jwt' &&\n (await nonRepudiation?.(response));\n return result;\n}\nconst retry = Symbol();\nexport async function genericGrantRequest(config, grantType, parameters, options) {\n checkConfig(config);\n const { as, c, auth, fetch, tlsOnly, timeout, decrypt } = int(config);\n const result = await oauth\n .genericTokenEndpointRequest(as, c, auth, grantType, new URLSearchParams(parameters), {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .then((response) => {\n let recognizedTokenTypes;\n if (grantType === 'urn:ietf:params:oauth:grant-type:token-exchange') {\n recognizedTokenTypes = { n_a: () => { } };\n }\n return oauth.processGenericTokenEndpointResponse(as, c, response, {\n [oauth.jweDecrypt]: decrypt,\n recognizedTokenTypes,\n });\n })\n .catch(errorHandler);\n addHelpers(result);\n return result;\n}\nexport async function tokenRevocation(config, token, parameters) {\n checkConfig(config);\n const { as, c, auth, fetch, tlsOnly, timeout } = int(config);\n return oauth\n .revocationRequest(as, c, auth, token, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n additionalParameters: new URLSearchParams(parameters),\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .then(oauth.processRevocationResponse)\n .catch(errorHandler);\n}\nexport async function fetchProtectedResource(config, accessToken, url, method, body, headers, options) {\n checkConfig(config);\n headers ||= new Headers();\n if (!headers.has('user-agent')) {\n headers.set('user-agent', USER_AGENT);\n }\n const { fetch, tlsOnly, timeout } = int(config);\n const exec = oauth.protectedResourceRequest(accessToken, method, url, headers, body, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n DPoP: options?.DPoP,\n signal: signal(timeout),\n });\n let result;\n try {\n result = await exec;\n }\n catch (err) {\n if (retryable(err, options)) {\n return fetchProtectedResource(config, accessToken, url, method, body, headers, {\n ...options,\n flag: retry,\n });\n }\n errorHandler(err);\n }\n return result;\n}\n//# sourceMappingURL=index.js.map","import {\n $inject,\n AlephaError,\n type Async,\n createDescriptor,\n Descriptor,\n KIND,\n} from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport {\n type AccessTokenResponse,\n type RealmDescriptor,\n SecurityError,\n SecurityProvider,\n type UserAccount,\n} from \"alepha/security\";\nimport {\n allowInsecureRequests,\n Configuration,\n discovery,\n refreshTokenGrant,\n} from \"openid-client\";\nimport type { OAuth2Profile } from \"../providers/ServerAuthProvider.ts\";\nimport type { Tokens } from \"../schemas/tokensSchema.ts\";\n\n/**\n * Creates an authentication provider descriptor for handling user login flows.\n *\n * Supports multiple authentication strategies: credentials (username/password), OAuth2,\n * and OIDC (OpenID Connect). Handles token management, user profile retrieval, and\n * integration with both external identity providers (Auth0, Keycloak) and internal realms.\n *\n * **Authentication Types**: Credentials, OAuth2 (Google, GitHub), OIDC, External providers\n *\n * @example\n * ```ts\n * class AuthProviders {\n * // Internal credentials-based auth\n * credentials = $auth({\n * realm: this.userRealm,\n * credentials: {\n * account: async ({ username, password }) => {\n * return await this.validateUser(username, password);\n * }\n * }\n * });\n *\n * // External OIDC provider\n * keycloak = $auth({\n * oidc: {\n * issuer: \"https://auth.example.com\",\n * clientId: \"my-app\",\n * clientSecret: \"secret\",\n * redirectUri: \"/auth/callback\"\n * }\n * });\n * }\n * ```\n */\nexport const $auth = (options: AuthDescriptorOptions): AuthDescriptor => {\n return createDescriptor(AuthDescriptor, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type AuthDescriptorOptions = {\n /**\n * Name of the identity provider.\n * If not provided, it will be derived from the property key.\n */\n name?: string;\n\n /**\n * If true, auth provider will be skipped.\n */\n disabled?: boolean;\n} & (AuthExternal | AuthInternal);\n\n/**\n * When you let an external service handle authentication. (e.g. Keycloak, Auth0, etc.)\n */\nexport type AuthExternal = {\n /**\n * Only OIDC is supported for external authentication.\n */\n oidc: OidcOptions;\n\n /**\n * For anonymous access, this will expect a service account access token.\n *\n * ```ts\n * class App {\n * anonymous = $serviceAccount(...);\n * auth = $auth({\n * // ... config ...\n * fallback: this.anonymous,\n * })\n * }\n * ```\n */\n fallback?: () => Async<AccessToken>;\n};\n\n/**\n * When using your own authentication system, e.g. using a database to store user accounts.\n * This is usually used with a custom login form.\n *\n * This relies on the `realm`, which is used to create/verify the access token.\n */\nexport type AuthInternal = {\n realm: RealmDescriptor;\n} & (\n | {\n /**\n * The common username/password authentication.\n *\n * - It uses the OAuth2 Client Credentials flow to obtain an access token.\n *\n * This is usually used with a custom login form on your website or mobile app.\n */\n credentials: CredentialsOptions;\n }\n | {\n /**\n * OAuth2 authentication. Delegates authentication to an OAuth2 provider. (e.g. Google, GitHub, etc.)\n *\n * - It uses the OAuth2 Authorization Code flow to obtain an access token and user information.\n *\n * This is usually used with a login button that redirects to the OAuth2 provider.\n */\n oauth: OAuth2Options;\n }\n | {\n /**\n * Like OAuth2, but uses OIDC (OpenID Connect) for authentication and user information retrieval.\n * OIDC is an identity layer on top of OAuth2, providing user authentication and profile information.\n *\n * - It uses the OAuth2 Authorization Code flow to obtain an access token and user information.\n * - PCKE (Proof Key for Code Exchange) is recommended for security.\n *\n * This is usually used with a login button that redirects to the OIDC provider.\n */\n oidc: OidcOptions;\n }\n);\n\nexport type CredentialsOptions = {\n account: CredentialsFn;\n};\n\nexport type CredentialsFn = (\n credentials: Credentials,\n) => Async<UserAccount | undefined>;\n\nexport interface Credentials {\n username: string;\n password: string;\n}\n\nexport interface OidcOptions {\n /**\n * URL of the OIDC issuer.\n */\n issuer: string;\n\n /**\n * Client ID for the OIDC client.\n */\n clientId: string;\n\n /**\n * Client secret for the OIDC client.\n * Optional if PKCE (Proof Key for Code Exchange) is used.\n */\n clientSecret?: string;\n\n /**\n * Redirect URI for the OIDC client.\n * This is where the user will be redirected after authentication.\n */\n redirectUri?: string;\n\n /**\n * For external auth providers only.\n * Take the ID token instead of the access token for validation.\n */\n useIdToken?: boolean;\n\n /**\n * URI to redirect the user after logout.\n */\n logoutUri?: string;\n\n /**\n * Optional scope for the OIDC client.\n * @default \"openid profile email\".\n */\n scope?: string;\n\n account?: LinkAccountFn;\n}\n\nexport interface LinkAccountOptions {\n access_token: string;\n user: OAuth2Profile;\n id_token?: string;\n expires_in?: number;\n scope?: string;\n}\n\nexport type LinkAccountFn = (tokens: LinkAccountOptions) => Async<UserAccount>;\n\nexport interface OAuth2Options {\n /**\n * URL of the OAuth2 authorization endpoint.\n */\n clientId: string;\n\n /**\n * Client secret for the OAuth2 client.\n */\n clientSecret: string;\n\n /**\n * URL of the OAuth2 authorization endpoint.\n */\n authorization: string;\n\n /**\n * URL of the OAuth2 token endpoint.\n */\n token: string;\n\n /**\n * Function to retrieve user profile information from the OAuth2 tokens.\n */\n userinfo: (tokens: Tokens) => Async<OAuth2Profile>;\n\n account?: LinkAccountFn;\n\n /**\n * URL of the OAuth2 authorization endpoint.\n */\n redirectUri?: string;\n\n /**\n * URL of the OAuth2 authorization endpoint.\n */\n scope?: string;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class AuthDescriptor extends Descriptor<AuthDescriptorOptions> {\n protected readonly securityProvider = $inject(SecurityProvider);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n\n public oauth?: Configuration;\n\n public get name() {\n return this.options.name ?? this.config.propertyKey;\n }\n\n public get jwks_uri(): string {\n const jwks = this.oauth?.serverMetadata().jwks_uri;\n if (!jwks) {\n throw new AlephaError(\"No JWKS URI available for the auth provider\");\n }\n return jwks;\n }\n\n public get scope(): string | undefined {\n if (\"oauth\" in this.options) {\n return this.options.oauth.scope;\n }\n if (\"oidc\" in this.options) {\n return this.options.oidc.scope || \"openid profile email\";\n }\n throw new AlephaError(\n \"No OAuth2 or OIDC configuration available for the auth provider\",\n );\n }\n\n public get redirect_uri() {\n if (\"oauth\" in this.options) {\n return this.options.oauth.redirectUri;\n }\n if (\"oidc\" in this.options) {\n return this.options.oidc.redirectUri;\n }\n throw new AlephaError(\n \"No OAuth2 or OIDC configuration available for the auth provider\",\n );\n }\n\n /**\n * Refreshes the access token using the refresh token.\n * Can be used on oauth2, oidc or credentials auth providers.\n */\n public async refresh(\n refreshToken: string,\n accessToken?: string,\n ): Promise<AccessTokenResponse> {\n if (\"realm\" in this.options) {\n return this.options.realm\n .refreshToken(refreshToken, accessToken)\n .then((it) => it.tokens)\n .catch((error) => {\n throw new SecurityError(\n \"Failed to refresh access token using the refresh token (realm)\",\n {\n cause: error,\n },\n );\n });\n } else if (this.oauth) {\n try {\n return {\n ...(await refreshTokenGrant(this.oauth, refreshToken)),\n issued_at: this.dateTimeProvider.now().unix(),\n };\n } catch (error) {\n throw new SecurityError(\n \"Failed to refresh access token using the refresh token (oauth2)\",\n {\n cause: error,\n },\n );\n }\n }\n\n throw new AlephaError(\n \"No realm or OAuth2 configuration available for refreshing the access token\",\n );\n }\n\n /**\n * Extracts user information from the access token.\n * This is used to create a user account from the access token.\n */\n public async user(tokens: Tokens): Promise<UserAccount> {\n try {\n if (\"oauth\" in this.options) {\n const profile = await this.options.oauth.userinfo(tokens);\n\n if (this.options.oauth.account) {\n return this.options.oauth.account({\n ...tokens,\n user: profile,\n });\n }\n\n return this.securityProvider.createUserFromPayload(profile);\n }\n\n if (\"oidc\" in this.options) {\n const payload = this.getUserFromIdToken(tokens.id_token || \"\");\n\n if (this.options.oidc.account) {\n return this.options.oidc.account({\n ...tokens,\n user: payload,\n });\n }\n\n return this.securityProvider.createUserFromPayload(payload);\n }\n } catch (error) {\n throw new SecurityError(\n \"Failed to extract user from identity provider tokens\",\n {\n cause: error,\n },\n );\n }\n\n throw new AlephaError(\n \"This authentication does not support user extraction from tokens\",\n );\n }\n\n protected getUserFromIdToken(idToken: string): OAuth2Profile {\n try {\n return JSON.parse(\n Buffer.from(idToken.split(\".\")[1], \"base64\").toString(\"utf8\"),\n ) as OAuth2Profile;\n } catch (error) {\n throw new AlephaError(\"Failed to parse ID Token payload\", {\n cause: error,\n });\n }\n }\n\n public async prepare() {\n const addons: Array<(config: Configuration) => void> = [];\n\n addons.push(allowInsecureRequests);\n\n if (\"oidc\" in this.options) {\n const { oidc } = this.options;\n\n this.oauth = await discovery(\n new URL(oidc.issuer),\n oidc.clientId,\n {\n client_secret: oidc.clientSecret,\n },\n undefined,\n {\n execute: addons,\n },\n );\n }\n\n if (\"oauth\" in this.options) {\n const { oauth } = this.options;\n\n this.oauth = new Configuration(\n {\n authorization_endpoint: oauth.authorization,\n token_endpoint: oauth.token,\n issuer: oauth.authorization, // use authorization URL as a pseudo-issuer?\n // we don't need all of these endpoints\n jwks_uri: undefined,\n end_session_endpoint: undefined,\n },\n oauth.clientId,\n {\n client_secret: oauth.clientSecret,\n },\n );\n }\n }\n}\n\n$auth[KIND] = AuthDescriptor;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type AccessToken = string | { token: () => Async<string> };\n\nexport interface WithLinkFn {\n link?: (name: string) => (opts: LinkAccountOptions) => Async<UserAccount>;\n}\n\nexport interface WithLoginFn {\n login?: (\n provider: string,\n ) => (creds: Credentials) => Async<UserAccount | undefined>;\n}\n","import { timingSafeEqual } from \"node:crypto\";\nimport { $hook, $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport {\n HttpError,\n type ServerRequest,\n ServerRouterProvider,\n} from \"alepha/server\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface BasicAuthOptions {\n username: string;\n password: string;\n}\n\nexport interface BasicAuthDescriptorConfig extends BasicAuthOptions {\n /** Name identifier for this basic auth (default: property key) */\n name?: string;\n /** Path patterns to match (supports wildcards like /devtools/*) */\n paths?: string[];\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class ServerBasicAuthProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n protected readonly routerProvider = $inject(ServerRouterProvider);\n protected readonly realm = \"Secure Area\";\n\n /**\n * Registered basic auth descriptors with their configurations\n */\n public readonly registeredAuths: BasicAuthDescriptorConfig[] = [];\n\n /**\n * Register a basic auth configuration (called by descriptors)\n */\n public registerAuth(config: BasicAuthDescriptorConfig): void {\n this.registeredAuths.push(config);\n }\n\n public readonly onStart = $hook({\n on: \"start\",\n handler: async () => {\n for (const auth of this.registeredAuths) {\n if (auth.paths) {\n for (const pattern of auth.paths) {\n const matchedRoutes = this.routerProvider.getRoutes(pattern);\n for (const route of matchedRoutes) {\n route.secure = {\n basic: {\n username: auth.username,\n password: auth.password,\n },\n };\n }\n }\n }\n }\n\n if (this.registeredAuths.length > 0) {\n this.log.info(\n `Initialized with ${this.registeredAuths.length} registered basic-auth configurations.`,\n );\n }\n },\n });\n\n /**\n * Hook into server:onRequest to check basic auth\n */\n public readonly onRequest = $hook({\n on: \"server:onRequest\",\n handler: async ({ route, request }) => {\n const routeAuth = route.secure;\n if (\n typeof routeAuth === \"object\" &&\n \"basic\" in routeAuth &&\n routeAuth.basic\n ) {\n this.checkAuth(request, routeAuth.basic);\n }\n },\n });\n\n /**\n * Hook into action:onRequest to check basic auth for actions\n */\n public readonly onActionRequest = $hook({\n on: \"action:onRequest\",\n handler: async ({ action, request }) => {\n const routeAuth = action.route.secure;\n if (isBasicAuth(routeAuth)) {\n this.checkAuth(request, routeAuth.basic);\n }\n },\n });\n\n /**\n * Check basic authentication\n */\n public checkAuth(request: ServerRequest, options: BasicAuthOptions): void {\n const authHeader = request.headers?.authorization;\n\n if (!authHeader || !authHeader.startsWith(\"Basic \")) {\n this.sendAuthRequired(request);\n throw new HttpError({\n status: 401,\n message: \"Authentication required\",\n });\n }\n\n // decode base64 credentials\n const base64Credentials = authHeader.slice(6); // Remove \"Basic \"\n const credentials = Buffer.from(base64Credentials, \"base64\").toString(\n \"utf-8\",\n );\n\n // split only on the first colon to handle passwords with colons\n const colonIndex = credentials.indexOf(\":\");\n const username =\n colonIndex !== -1 ? credentials.slice(0, colonIndex) : credentials;\n const password = colonIndex !== -1 ? credentials.slice(colonIndex + 1) : \"\";\n\n // verify credentials using timing-safe comparison to prevent timing attacks\n const isValid = this.timingSafeCredentialCheck(\n username,\n password,\n options.username,\n options.password,\n );\n\n if (!isValid) {\n this.sendAuthRequired(request);\n this.log.warn(`Failed basic auth attempt for user`, {\n username,\n });\n throw new HttpError({\n status: 401,\n message: \"Invalid credentials\",\n });\n }\n }\n\n /**\n * Performs a timing-safe comparison of credentials to prevent timing attacks.\n * Always compares both username and password to avoid leaking which one is wrong.\n */\n protected timingSafeCredentialCheck(\n inputUsername: string,\n inputPassword: string,\n expectedUsername: string,\n expectedPassword: string,\n ): boolean {\n // Convert to buffers for timing-safe comparison\n const inputUserBuf = Buffer.from(inputUsername, \"utf-8\");\n const expectedUserBuf = Buffer.from(expectedUsername, \"utf-8\");\n const inputPassBuf = Buffer.from(inputPassword, \"utf-8\");\n const expectedPassBuf = Buffer.from(expectedPassword, \"utf-8\");\n\n // timingSafeEqual requires same-length buffers\n // When lengths differ, we compare against a dummy buffer to maintain constant time\n const userMatch = this.safeCompare(inputUserBuf, expectedUserBuf);\n const passMatch = this.safeCompare(inputPassBuf, expectedPassBuf);\n\n // Both must match - bitwise AND avoids short-circuit evaluation\n // eslint-disable-next-line no-bitwise\n return (userMatch & passMatch) === 1;\n }\n\n /**\n * Compares two buffers in constant time, handling different lengths safely.\n * Returns 1 if equal, 0 if not equal.\n */\n protected safeCompare(input: Buffer, expected: Buffer): number {\n // If lengths differ, compare input against itself to maintain timing\n // but return 0 (not equal)\n if (input.length !== expected.length) {\n // Still perform a comparison to keep timing consistent\n timingSafeEqual(input, input);\n return 0;\n }\n\n return timingSafeEqual(input, expected) ? 1 : 0;\n }\n\n /**\n * Send WWW-Authenticate header\n */\n protected sendAuthRequired(request: ServerRequest): void {\n request.reply.setHeader(\"WWW-Authenticate\", `Basic realm=\"${this.realm}\"`);\n }\n}\n\nexport const isBasicAuth = (\n value: unknown,\n): value is { basic: BasicAuthOptions } => {\n return (\n typeof value === \"object\" && !!value && \"basic\" in value && !!value.basic\n );\n};\n","import { $inject, createDescriptor, Descriptor, KIND } from \"alepha\";\nimport type { ServerRequest } from \"alepha/server\";\nimport type {\n BasicAuthDescriptorConfig,\n BasicAuthOptions,\n} from \"../providers/ServerBasicAuthProvider.ts\";\nimport { ServerBasicAuthProvider } from \"../providers/ServerBasicAuthProvider.ts\";\n\n/**\n * Declares HTTP Basic Authentication for server routes.\n * This descriptor provides methods to protect routes with username/password authentication.\n */\nexport const $basicAuth = (\n options: BasicAuthDescriptorConfig,\n): AbstractBasicAuthDescriptor => {\n return createDescriptor(BasicAuthDescriptor, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface AbstractBasicAuthDescriptor {\n readonly name: string;\n readonly options: BasicAuthDescriptorConfig;\n check(request: ServerRequest, options?: BasicAuthOptions): void;\n}\n\nexport class BasicAuthDescriptor\n extends Descriptor<BasicAuthDescriptorConfig>\n implements AbstractBasicAuthDescriptor\n{\n protected readonly serverBasicAuthProvider = $inject(ServerBasicAuthProvider);\n\n public get name(): string {\n return this.options.name ?? `${this.config.propertyKey}`;\n }\n\n protected onInit() {\n // Register this auth configuration with the provider\n this.serverBasicAuthProvider.registerAuth(this.options);\n }\n\n /**\n * Checks basic auth for the given request using this descriptor's configuration.\n */\n public check(request: ServerRequest, options?: BasicAuthOptions): void {\n const mergedOptions = { ...this.options, ...options };\n this.serverBasicAuthProvider.checkAuth(request, mergedOptions);\n }\n}\n\n$basicAuth[KIND] = BasicAuthDescriptor;\n","import { randomUUID } from \"node:crypto\";\nimport { $hook, $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport {\n JwtProvider,\n type Permission,\n SecurityProvider,\n type UserAccountToken,\n userAccountInfoSchema,\n} from \"alepha/security\";\nimport {\n $action,\n ForbiddenError,\n type ServerRequest,\n UnauthorizedError,\n} from \"alepha/server\";\nimport {\n type BasicAuthOptions,\n isBasicAuth,\n} from \"./ServerBasicAuthProvider.ts\";\n\nexport class ServerSecurityProvider {\n protected readonly log = $logger();\n protected readonly securityProvider = $inject(SecurityProvider);\n protected readonly jwtProvider = $inject(JwtProvider);\n protected readonly alepha = $inject(Alepha);\n\n protected readonly onConfigure = $hook({\n on: \"configure\",\n handler: async () => {\n for (const action of this.alepha.descriptors($action)) {\n // -------------------------------------------------------------------------------------------------------------\n // if the action is disabled or not secure, we do NOT create a permission for it\n // -------------------------------------------------------------------------------------------------------------\n if (\n action.options.disabled ||\n action.options.secure === false ||\n this.securityProvider.getRealms().length === 0\n ) {\n continue;\n }\n\n const secure = action.options.secure;\n if (typeof secure !== \"object\") {\n this.securityProvider.createPermission({\n name: action.name,\n group: action.group,\n method: action.route.method,\n path: action.route.path,\n });\n }\n }\n },\n });\n\n // -------------------------------------------------------------------------------------------------------------------\n\n protected readonly onActionRequest = $hook({\n on: \"action:onRequest\",\n handler: async ({ action, request, options }) => {\n // if you set explicitly secure: false, we assume you don't want any security check\n // but only if no user is provided in options\n if (action.options.secure === false && !options.user) {\n this.log.trace(\"Skipping security check for route\");\n return;\n }\n\n if (isBasicAuth(action.route.secure)) {\n return;\n }\n\n const permission = this.securityProvider\n .getPermissions()\n .find(\n (it) =>\n it.path === action.route.path && it.method === action.route.method,\n );\n\n try {\n request.user = this.createUserFromLocalFunctionContext(\n options,\n permission,\n );\n\n const route = action.route;\n if (typeof route.secure === \"object\") {\n this.check(request.user, route.secure);\n }\n\n this.alepha.state.set(\n \"alepha.server.request.user\",\n this.alepha.codec.decode(userAccountInfoSchema, request.user),\n );\n } catch (error) {\n if (action.options.secure || permission) {\n throw error;\n }\n // else, we skip the security check\n this.log.trace(\"Skipping security check for action\");\n }\n },\n });\n\n protected readonly onRequest = $hook({\n on: \"server:onRequest\",\n priority: \"last\",\n handler: async ({ request, route }) => {\n // if you set explicitly secure: false, we assume you don't want any security check\n if (route.secure === false) {\n this.log.trace(\n \"Skipping security check for route - explicitly disabled\",\n );\n return;\n }\n\n if (isBasicAuth(route.secure)) {\n return;\n }\n\n const permission = this.securityProvider\n .getPermissions()\n .find((it) => it.path === route.path && it.method === route.method);\n\n if (!request.headers.authorization && !route.secure && !permission) {\n this.log.trace(\n \"Skipping security check for route - no authorization header and not secure\",\n );\n return;\n }\n\n try {\n // set user to request\n request.user = await this.securityProvider.createUserFromToken(\n request.headers.authorization,\n { permission },\n );\n\n if (typeof route.secure === \"object\") {\n this.check(request.user, route.secure);\n }\n\n this.alepha.state.set(\n \"alepha.server.request.user\",\n // remove sensitive info\n this.alepha.codec.decode(userAccountInfoSchema, request.user),\n );\n\n this.log.trace(\"User set from request token\", {\n user: request.user,\n permission,\n });\n } catch (error) {\n if (route.secure || permission) {\n throw error;\n }\n\n // else, we skip the security check\n this.log.trace(\n \"Skipping security check for route - error occurred\",\n error,\n );\n }\n },\n });\n\n // -------------------------------------------------------------------------------------------------------------------\n\n protected check(user: UserAccountToken, secure: ServerRouteSecure) {\n if (secure.realm) {\n if (user.realm !== secure.realm) {\n throw new ForbiddenError(\n `User must belong to realm '${secure.realm}' to access this route`,\n );\n }\n }\n }\n\n /**\n * Get the user account token for a local action call.\n * There are three possible sources for the user:\n * - `options.user`: the user passed in the options\n * - `\"system\"`: the system user from the state (you MUST set state `server.security.system.user`)\n * - `\"context\"`: the user from the request context (you MUST be in an HTTP request context)\n *\n * Priority order: `options.user` > `\"system\"` > `\"context\"`.\n *\n * In testing environment, if no user is provided, a test user is created based on the SecurityProvider's roles.\n */\n protected createUserFromLocalFunctionContext(\n options: { user?: UserAccountToken | \"system\" | \"context\" },\n permission?: Permission,\n ): UserAccountToken {\n const fromOptions =\n typeof options.user === \"object\" ? options.user : undefined;\n\n const type = typeof options.user === \"string\" ? options.user : undefined;\n\n let user: UserAccountToken | undefined;\n\n const fromContext = this.alepha.context.get<ServerRequest>(\"request\")?.user;\n const fromSystem = this.alepha.state.get(\n \"alepha.server.security.system.user\",\n );\n\n if (type === \"system\") {\n user = fromSystem;\n } else if (type === \"context\") {\n user = fromContext;\n } else {\n user = fromOptions ?? fromContext ?? fromSystem;\n }\n\n if (!user) {\n // in testing mode, we create a test user\n if (this.alepha.isTest() && !(\"user\" in options)) {\n return this.createTestUser();\n }\n\n throw new UnauthorizedError(\"User is required for calling this action\");\n }\n\n const roles =\n user.roles ??\n (this.alepha.isTest()\n ? this.securityProvider.getRoles().map((role) => role.name)\n : []);\n let ownership: boolean | string | undefined;\n\n if (permission) {\n const result = this.securityProvider.checkPermission(\n permission,\n ...roles,\n );\n if (!result.isAuthorized) {\n throw new ForbiddenError(\n `Permission '${this.securityProvider.permissionToString(permission)}' is required for this route`,\n );\n }\n ownership = result.ownership;\n }\n\n // create a new user object with ownership if needed\n return {\n ...user,\n ownership,\n };\n }\n\n // ---------------------------------------------------------------------------------------------------------------\n // TESTING ONLY\n // ---------------------------------------------------------------------------------------------------------------\n\n protected createTestUser(): UserAccountToken {\n return {\n id: randomUUID(),\n name: \"Test\",\n roles: this.securityProvider.getRoles().map((role) => role.name),\n };\n }\n\n protected readonly onClientRequest = $hook({\n on: \"client:onRequest\",\n handler: async ({ request, options }) => {\n if (!this.alepha.isTest()) {\n return;\n }\n\n // skip helper if user is explicitly set to undefined\n if (\"user\" in options && options.user === undefined) {\n return;\n }\n\n request.headers = new Headers(request.headers);\n\n if (!request.headers.has(\"authorization\")) {\n const test = this.createTestUser();\n const user =\n typeof options?.user === \"object\" ? options.user : undefined;\n const sub = user?.id ?? test.id;\n const roles = user?.roles ?? test.roles;\n\n const token = await this.jwtProvider.create(\n {\n sub,\n roles,\n },\n user?.realm ?? this.securityProvider.getRealms()[0]?.name,\n );\n\n request.headers.set(\"authorization\", `Bearer ${token}`);\n }\n },\n });\n}\n\nexport type ServerRouteSecure = {\n realm?: string;\n basic?: BasicAuthOptions;\n};\n","import { $module } from \"alepha\";\nimport {\n $permission,\n $realm,\n $role,\n AlephaSecurity,\n type UserAccount,\n type UserAccountToken,\n} from \"alepha/security\";\nimport { AlephaServer, type FetchOptions } from \"alepha/server\";\nimport { $basicAuth } from \"./descriptors/$basicAuth.ts\";\nimport { ServerBasicAuthProvider } from \"./providers/ServerBasicAuthProvider.ts\";\nimport {\n type ServerRouteSecure,\n ServerSecurityProvider,\n} from \"./providers/ServerSecurityProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./descriptors/$basicAuth.ts\";\nexport * from \"./providers/ServerBasicAuthProvider.ts\";\nexport * from \"./providers/ServerSecurityProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha\" {\n interface State {\n /**\n * Real (or fake) user account, used for internal actions.\n *\n * If you define this, you assume that all actions are executed by this user by default.\n * > To force a different user, you need to pass it explicitly in the options.\n */\n\n \"alepha.server.security.system.user\"?: UserAccountToken;\n\n /**\n * The authenticated user account attached to the server request state.\n *\n * @internal\n */\n \"alepha.server.request.user\"?: UserAccount;\n }\n}\n\ndeclare module \"alepha/server\" {\n interface ServerRequest<TConfig> {\n user?: UserAccountToken; // for all routes, user is maybe present\n }\n\n interface ServerActionRequest<TConfig> {\n user: UserAccountToken; // for actions, user is always present\n }\n\n interface ServerRoute {\n /**\n * If true, the route will be protected by the security provider.\n * All actions are secure by default, but you can disable it for specific actions.\n */\n secure?: boolean | ServerRouteSecure;\n }\n\n interface ClientRequestOptions extends FetchOptions {\n /**\n * Forward user from the previous request.\n * If \"system\", use system user. @see {ServerSecurityProvider.localSystemUser}\n * If \"context\", use the user from the current context (e.g. request).\n *\n * @default \"system\" if provided, else \"context\" if available.\n */\n user?: UserAccountToken | \"system\" | \"context\";\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Plugin for Alepha Server that provides security features. Based on the Alepha Security module.\n *\n * By default, all $action will be guarded by a permission check.\n *\n * @see {@link ServerSecurityProvider}\n * @module alepha.server.security\n */\nexport const AlephaServerSecurity = $module({\n name: \"alepha.server.security\",\n descriptors: [$realm, $role, $permission, $basicAuth],\n services: [\n AlephaServer,\n AlephaSecurity,\n ServerSecurityProvider,\n ServerBasicAuthProvider,\n ],\n});\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const apiLinkSchema = t.object({\n name: t.text({\n description: \"Name of the API link, used for identification.\",\n }),\n\n group: t.optional(\n t.text({\n description:\n \"Group to which the API link belongs, used for categorization.\",\n }),\n ),\n\n path: t.text({\n description: \"Pathname used to access the API link.\",\n }),\n\n method: t.optional(\n t.text({\n description:\n \"HTTP method used for the API link, e.g., GET, POST, etc. If not specified, defaults to GET.\",\n }),\n ),\n\n requestBodyType: t.optional(\n t.text({\n description:\n \"Type of the request body for the API link. Default is application/json for POST/PUT/PATCH, null for others.\",\n }),\n ),\n\n service: t.optional(\n t.text({\n description:\n \"Service name associated with the API link, used for service discovery.\",\n }),\n ),\n});\n\nexport const apiLinksResponseSchema = t.object({\n prefix: t.optional(t.text()),\n links: t.array(apiLinkSchema),\n});\n\nexport type ApiLinksResponse = Static<typeof apiLinksResponseSchema>;\nexport type ApiLink = Static<typeof apiLinkSchema>;\n","import { $inject, Alepha, AlephaError, type Async, t } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport {\n type ActionDescriptor,\n type ClientRequestEntry,\n type ClientRequestOptions,\n type ClientRequestResponse,\n type FetchResponse,\n HttpClient,\n type RequestConfigSchema,\n ServerReply,\n type ServerRequest,\n type ServerRequestConfigEntry,\n type ServerResponseBody,\n UnauthorizedError,\n} from \"alepha/server\";\nimport type { ServerRouteSecure } from \"alepha/server/security\";\nimport {\n type ApiLink,\n apiLinksResponseSchema,\n} from \"../schemas/apiLinksResponseSchema.ts\";\n\n/**\n * Browser, SSR friendly, service to handle links.\n */\nexport class LinkProvider {\n static path = {\n apiLinks: \"/api/_links\",\n apiSchema: \"/api/_links/:name/schema\",\n };\n\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly httpClient = $inject(HttpClient);\n\n // all server links (local + remote)\n // THIS IS NOT USER LINKS! (which are filtered by permissions)\n protected serverLinks: Array<HttpClientLink> = [];\n\n /**\n * Get applicative links registered on the server.\n * This does not include lazy-loaded remote links.\n */\n public getServerLinks(): HttpClientLink[] {\n if (this.alepha.isBrowser()) {\n this.log.warn(\n \"Getting server links in the browser is not supported. Use `fetchLinks` to get links from the server.\",\n );\n return [];\n }\n\n return this.serverLinks;\n }\n\n /**\n * Register a new link for the application.\n */\n public registerLink(link: HttpClientLink): void {\n if (this.alepha.isBrowser()) {\n this.log.warn(\n \"Registering links in the browser is not supported. Use `fetchLinks` to get links from the server.\",\n );\n return;\n }\n\n if (!link.handler && !link.host) {\n throw new AlephaError(\n \"Can't create link - 'handler' or 'host' is required\",\n );\n }\n\n if (this.serverLinks.some((l) => l.name === link.name)) {\n // remove existing link with the same name\n this.serverLinks = this.serverLinks.filter((l) => l.name !== link.name);\n }\n\n this.serverLinks.push(link);\n }\n\n public get links(): HttpClientLink[] {\n // TODO: not performant at all, use a map instead for ServerLinks\n const apiLinks = this.alepha.state.get(\n \"alepha.server.request.apiLinks\",\n )?.links;\n if (apiLinks) {\n if (this.alepha.isBrowser()) {\n return apiLinks;\n }\n\n const links = [];\n for (const link of apiLinks) {\n const originalLink = this.serverLinks.find((l) => l.name === link.name);\n if (originalLink) {\n links.push(originalLink);\n }\n }\n return links;\n }\n\n return this.serverLinks ?? [];\n }\n\n /**\n * Force browser to refresh links from the server.\n */\n public async fetchLinks(): Promise<HttpClientLink[]> {\n const { data } = await this.httpClient.fetch(\n `${LinkProvider.path.apiLinks}`,\n {\n method: \"GET\",\n schema: {\n response: apiLinksResponseSchema,\n },\n },\n );\n\n this.alepha.state.set(\"alepha.server.request.apiLinks\", data);\n\n return data.links;\n }\n\n /**\n * Create a virtual client that can be used to call actions.\n *\n * Use js Proxy under the hood.\n */\n public client<T extends object>(\n scope: ClientScope = {},\n ): HttpVirtualClient<T> {\n return new Proxy<HttpVirtualClient<T>>({} as HttpVirtualClient<T>, {\n get: (_, prop) => {\n if (typeof prop !== \"string\") {\n return;\n }\n\n return this.createVirtualAction<RequestConfigSchema>(prop, scope);\n },\n });\n }\n\n /**\n * Check if a link with the given name exists.\n * @param name\n */\n public can(name: string): boolean {\n return this.links.some((link) => link.name === name);\n }\n\n /**\n * Resolve a link by its name and call it.\n * - If link is local, it will call the local handler.\n * - If link is remote, it will make a fetch request to the remote server.\n */\n public async follow(\n name: string,\n config: Partial<ServerRequestConfigEntry> = {},\n options: ClientRequestOptions & ClientScope = {},\n ): Promise<any> {\n this.log.trace(\"Following link\", { name, config, options });\n const link = await this.getLinkByName(name, options);\n\n // if a handler is defined, use it (ssr)\n if (link.handler && !options.request) {\n this.log.trace(\"Local link found\", { name });\n return link.handler(\n {\n method: link.method,\n url: new URL(`http://localhost${link.path}`),\n query: config.query ?? {},\n body: config.body ?? {},\n params: config.params ?? {},\n headers: config.headers ?? {},\n metadata: {},\n reply: new ServerReply(),\n } as Partial<ServerRequest> as ServerRequest,\n options,\n );\n }\n\n this.log.trace(\"Remote link found\", {\n name,\n host: link.host,\n service: link.service,\n });\n\n return this.followRemote(link, config, options).then(\n (response) => response.data,\n );\n }\n\n protected createVirtualAction<T extends RequestConfigSchema>(\n name: string,\n scope: ClientScope = {},\n ): VirtualAction<T> {\n const $: VirtualAction<T> = async (\n config: any = {},\n options: ClientRequestOptions = {},\n ) => {\n return this.follow(name, config, {\n ...scope,\n ...options,\n });\n };\n\n Object.defineProperty($, \"name\", {\n value: name,\n writable: false,\n });\n\n $.run = async (config: any = {}, options: ClientRequestOptions = {}) => {\n return this.follow(name, config, {\n ...scope,\n ...options,\n });\n };\n\n $.fetch = async (config: any = {}, options: ClientRequestOptions = {}) => {\n const link = await this.getLinkByName(name, scope);\n return this.followRemote(link, config, options);\n };\n\n $.can = () => {\n return this.can(name);\n };\n\n return $;\n }\n\n protected async followRemote(\n link: HttpClientLink,\n config: Partial<ServerRequestConfigEntry> = {},\n options: ClientRequestOptions = {},\n ): Promise<FetchResponse> {\n options.request ??= {};\n options.request.headers = new Headers(options.request.headers);\n\n const als = this.alepha.context.get<ServerRequest>(\"request\");\n if (als?.headers.authorization) {\n options.request.headers.set(\"authorization\", als.headers.authorization);\n }\n\n const context = this.alepha.context.get(\"context\");\n if (typeof context === \"string\") {\n options.request.headers.set(\"x-request-id\", context);\n }\n\n const action = {\n ...link,\n // schema is not used in the client,\n // we assume that typescript will check\n schema: {\n body: t.any(),\n response: t.any(),\n },\n };\n\n // prefix with service when host is not defined (e.g. browser)\n if (!link.host && link.service) {\n action.path = `/${link.service}${action.path}`;\n }\n\n action.path = `${action.prefix ?? \"/api\"}${action.path}`;\n action.prefix = undefined; // prefix is not used in the client\n\n // else, make a request\n return this.httpClient.fetchAction({\n host: link.host,\n config,\n options,\n action: action as any, // schema.body TAny is not accepted\n });\n }\n\n protected async getLinkByName(\n name: string,\n options: ClientScope = {},\n ): Promise<HttpClientLink> {\n if (\n this.alepha.isBrowser() &&\n !this.alepha.state.get(\"alepha.server.request.apiLinks\")\n ) {\n await this.fetchLinks();\n }\n\n const link = this.links.find(\n (a) =>\n a.name === name &&\n (!options.group || a.group === options.group) &&\n (!options.service || options.service === a.service),\n );\n\n if (!link) {\n const error = new UnauthorizedError(`Action ${name} not found.`);\n // mimic http error handling\n await this.alepha.events.emit(\"client:onError\", {\n route: link,\n error,\n });\n throw error;\n }\n\n if (options.hostname) {\n return {\n ...link,\n host: options.hostname,\n };\n }\n\n return link;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface HttpClientLink extends ApiLink {\n secured?: boolean | ServerRouteSecure;\n prefix?: string;\n // -- server only --\n // only for remote actions\n host?: string;\n service?: string;\n // used only for local actions, not for remote actions\n schema?: RequestConfigSchema;\n handler?: (\n request: ServerRequest,\n options: ClientRequestOptions,\n ) => Async<ServerResponseBody>;\n}\n\nexport interface ClientScope {\n group?: string;\n service?: string;\n hostname?: string;\n}\n\nexport type HttpVirtualClient<T> = {\n [K in keyof T as T[K] extends ActionDescriptor<RequestConfigSchema>\n ? K\n : never]: T[K] extends ActionDescriptor<infer Schema>\n ? VirtualAction<Schema>\n : never;\n};\n\nexport interface VirtualAction<T extends RequestConfigSchema>\n extends Pick<ActionDescriptor<T>, \"name\" | \"run\" | \"fetch\"> {\n (\n config?: ClientRequestEntry<T>,\n opts?: ClientRequestOptions,\n ): Promise<ClientRequestResponse<T>>;\n can: () => boolean;\n}\n","import { $inject, KIND } from \"alepha\";\nimport {\n type ClientScope,\n type HttpVirtualClient,\n LinkProvider,\n} from \"../providers/LinkProvider.ts\";\n\n/**\n * Create a new client.\n */\nexport const $client = <T extends object>(\n scope?: ClientScope,\n): HttpVirtualClient<T> => {\n return $inject(LinkProvider).client<T>(scope);\n};\n\n$client[KIND] = \"$client\";\n","import { createDescriptor, Descriptor, KIND } from \"alepha\";\nimport type { ServiceAccountDescriptor } from \"alepha/security\";\nimport type { ProxyDescriptorOptions } from \"alepha/server/proxy\";\n\n/**\n * $remote is a descriptor that allows you to define remote service access.\n *\n * Use it only when you have 2 or more services that need to communicate with each other.\n *\n * All remote services can be exposed as actions, ... or not.\n *\n * You can add a service account if you want to use a security layer.\n */\nexport const $remote = (options: RemoteDescriptorOptions) => {\n return createDescriptor(RemoteDescriptor, options);\n};\n\nexport interface RemoteDescriptorOptions {\n /**\n * The URL of the remote service.\n * You can use a function to generate the URL dynamically.\n * You probably should use $env(env) to get the URL from the environment.\n *\n * @example\n * ```ts\n * import { $remote } from \"alepha/server\";\n * import { $inject, t } from \"alepha\";\n *\n * class App {\n * env = $env(t.object({\n * REMOTE_URL: t.text({default: \"http://localhost:3000\"}),\n * }));\n * remote = $remote({\n * url: this.env.REMOTE_URL,\n * });\n * }\n * ```\n */\n url: string | (() => string);\n\n /**\n * The name of the remote service.\n *\n * @default Member of the class containing the remote service.\n */\n name?: string;\n\n /**\n * If true, all methods of the remote service will be exposed as actions in this context.\n * > Note: Proxy will never use the service account, it just... proxies the request.\n */\n proxy?:\n | boolean\n | Partial<\n ProxyDescriptorOptions & {\n /**\n * If true, the remote service won't be available internally, only through the proxy.\n */\n noInternal: boolean;\n }\n >;\n\n /**\n * For communication between the server and the remote service with a security layer.\n * This will be used for internal communication and will not be exposed to the client.\n */\n serviceAccount?: ServiceAccountDescriptor;\n}\n\nexport class RemoteDescriptor extends Descriptor<RemoteDescriptorOptions> {\n public get name(): string {\n return this.options.name ?? this.config.propertyKey;\n }\n}\n\n$remote[KIND] = RemoteDescriptor;\n","import { type Async, createDescriptor, Descriptor, KIND } from \"alepha\";\nimport type { ServerRequest } from \"alepha/server\";\n\n/**\n * Creates a proxy descriptor to forward requests to another server.\n *\n * This descriptor enables you to create reverse proxy functionality, allowing your Alepha server\n * to forward requests to other services while maintaining a unified API surface. It's particularly\n * useful for microservice architectures, API gateways, or when you need to aggregate multiple\n * services behind a single endpoint.\n *\n * **Key Features**\n *\n * - **Path-based routing**: Match specific paths or patterns to proxy\n * - **Dynamic targets**: Support both static and dynamic target resolution\n * - **Request/Response hooks**: Modify requests before forwarding and responses after receiving\n * - **URL rewriting**: Transform URLs before forwarding to the target\n * - **Conditional proxying**: Enable/disable proxies based on environment or conditions\n *\n * @example\n * **Basic proxy setup:**\n * ```ts\n * import { $proxy } from \"alepha/server/proxy\";\n *\n * class ApiGateway {\n * // Forward all /api/* requests to external service\n * api = $proxy({\n * path: \"/api/*\",\n * target: \"https://api.example.com\"\n * });\n * }\n * ```\n *\n * @example\n * **Dynamic target with environment-based routing:**\n * ```ts\n * class ApiGateway {\n * // Route to different environments based on configuration\n * api = $proxy({\n * path: \"/api/*\",\n * target: () => process.env.NODE_ENV === \"production\"\n * ? \"https://api.prod.example.com\"\n * : \"https://api.dev.example.com\"\n * });\n * }\n * ```\n *\n * @example\n * **Advanced proxy with request/response modification:**\n * ```ts\n * class SecureProxy {\n * secure = $proxy({\n * path: \"/secure/*\",\n * target: \"https://secure-api.example.com\",\n * beforeRequest: async (request, proxyRequest) => {\n * // Add authentication headers\n * proxyRequest.headers = {\n * ...proxyRequest.headers,\n * 'Authorization': `Bearer ${await getServiceToken()}`,\n * 'X-Forwarded-For': request.headers['x-forwarded-for'] || request.ip\n * };\n * },\n * afterResponse: async (request, proxyResponse) => {\n * // Log response for monitoring\n * console.log(`Proxied ${request.url} -> ${proxyResponse.status}`);\n * },\n * rewrite: (url) => {\n * // Remove /secure prefix when forwarding\n * url.pathname = url.pathname.replace('/secure', '');\n * }\n * });\n * }\n * ```\n *\n * @example\n * **Conditional proxy based on feature flags:**\n * ```ts\n * class FeatureProxy {\n * newApi = $proxy({\n * path: \"/v2/*\",\n * target: \"https://new-api.example.com\",\n * disabled: !process.env.ENABLE_V2_API // Disable if feature flag is off\n * });\n * }\n * ```\n */\nexport const $proxy = (options: ProxyDescriptorOptions): ProxyDescriptor => {\n return createDescriptor(ProxyDescriptor, options);\n};\n\nexport type ProxyDescriptorOptions = {\n /**\n * Path pattern to match for proxying requests.\n *\n * Supports wildcards and path parameters:\n * - `/api/*` - Matches all paths starting with `/api/`\n * - `/api/v1/*` - Matches all paths starting with `/api/v1/`\n * - `/users/:id` - Matches `/users/123`, `/users/abc`, etc.\n *\n * @example \"/api/*\"\n * @example \"/secure/admin/*\"\n * @example \"/users/:id/posts\"\n */\n path: string;\n\n /**\n * Target URL to which matching requests should be forwarded.\n *\n * Can be either:\n * - **Static string**: A fixed URL like `\"https://api.example.com\"`\n * - **Dynamic function**: A function that returns the URL, enabling runtime target resolution\n *\n * The target URL will be combined with the remaining path from the original request.\n *\n * @example \"https://api.example.com\"\n * @example () => process.env.API_URL || \"http://localhost:3001\"\n */\n target: string | (() => string);\n\n /**\n * Whether this proxy is disabled.\n *\n * When `true`, requests matching the path will not be proxied and will be handled\n * by other routes or return 404. Useful for feature toggles or conditional proxying.\n *\n * @default false\n * @example !process.env.ENABLE_PROXY\n */\n disabled?: boolean;\n\n /**\n * Hook called before forwarding the request to the target server.\n *\n * Use this to:\n * - Add authentication headers\n * - Modify request headers or body\n * - Add request tracking/logging\n * - Transform the request before forwarding\n *\n * @param request - The original incoming server request\n * @param proxyRequest - The request that will be sent to the target (modifiable)\n *\n * @example\n * ```ts\n * beforeRequest: async (request, proxyRequest) => {\n * proxyRequest.headers = {\n * ...proxyRequest.headers,\n * 'Authorization': `Bearer ${await getToken()}`,\n * 'X-Request-ID': generateRequestId()\n * };\n * }\n * ```\n */\n beforeRequest?: (\n request: ServerRequest,\n proxyRequest: RequestInit,\n ) => Async<void>;\n\n /**\n * Hook called after receiving the response from the target server.\n *\n * Use this to:\n * - Log response details for monitoring\n * - Add custom headers to the response\n * - Transform response data\n * - Handle error responses\n *\n * @param request - The original incoming server request\n * @param proxyResponse - The response received from the target server\n *\n * @example\n * ```ts\n * afterResponse: async (request, proxyResponse) => {\n * console.log(`Proxy ${request.method} ${request.url} -> ${proxyResponse.status}`);\n *\n * if (!proxyResponse.ok) {\n * await logError(`Proxy error: ${proxyResponse.status}`, { request, response: proxyResponse });\n * }\n * }\n * ```\n */\n afterResponse?: (\n request: ServerRequest,\n proxyResponse: Response,\n ) => Async<void>;\n\n /**\n * Function to rewrite the URL before sending to the target server.\n *\n * Use this to:\n * - Remove or add path prefixes\n * - Transform path parameters\n * - Modify query parameters\n * - Change the URL structure entirely\n *\n * The function receives a mutable URL object and should modify it in-place.\n *\n * @param url - The URL object to modify (mutable)\n *\n * @example\n * ```ts\n * // Remove /api prefix when forwarding\n * rewrite: (url) => {\n * url.pathname = url.pathname.replace('/api', '');\n * }\n * ```\n *\n * @example\n * ```ts\n * // Add version prefix\n * rewrite: (url) => {\n * url.pathname = `/v2${url.pathname}`;\n * }\n * ```\n */\n rewrite?: (url: URL) => void;\n\n // TODO: Add retry functionality\n // retry?: RetryOptions;\n};\n\nexport class ProxyDescriptor extends Descriptor<ProxyDescriptorOptions> {}\n\n$proxy[KIND] = ProxyDescriptor;\n","import { ReadableStream as WebStream } from \"node:stream/web\";\nimport { $hook, $inject, Alepha, AlephaError } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport {\n routeMethods,\n type ServerHandler,\n type ServerRequest,\n ServerRouterProvider,\n} from \"alepha/server\";\nimport { $proxy, type ProxyDescriptorOptions } from \"../descriptors/$proxy.ts\";\n\nexport class ServerProxyProvider {\n protected readonly log = $logger();\n protected readonly routerProvider = $inject(ServerRouterProvider);\n protected readonly alepha = $inject(Alepha);\n\n protected readonly configure = $hook({\n on: \"configure\",\n handler: () => {\n for (const proxy of this.alepha.descriptors($proxy)) {\n this.createProxy(proxy.options);\n }\n },\n });\n\n public createProxy(options: ProxyDescriptorOptions): void {\n if (options.disabled) {\n return;\n }\n\n const path = options.path;\n const target =\n typeof options.target === \"function\" ? options.target() : options.target;\n\n if (!path.endsWith(\"/*\")) {\n throw new AlephaError(\"Proxy path should end with '/*'\");\n }\n\n // Extract base path without /*\n const handler = this.createProxyHandler(target, options);\n\n for (const method of routeMethods) {\n this.routerProvider.createRoute({\n method,\n path,\n handler,\n });\n }\n\n this.log.info(\"Proxying\", { path, target });\n }\n\n public createProxyHandler(\n target: string,\n options: Omit<ProxyDescriptorOptions, \"path\">,\n ): ServerHandler {\n return async (request) => {\n const url = new URL(target + request.url.pathname);\n if (request.url.search) {\n url.search = request.url.search;\n }\n\n options.rewrite?.(url);\n\n const requestInit = {\n url: url.toString(),\n method: request.method,\n headers: {\n ...request.headers,\n \"accept-encoding\": \"identity\", // ignore compression\n },\n body: this.getRawRequestBody(request),\n };\n\n if (requestInit.body) {\n (requestInit as any).duplex = \"half\";\n }\n\n if (options.beforeRequest) {\n await options.beforeRequest(request, requestInit);\n }\n\n this.log.debug(\"Proxying request\", {\n url: url.toString(),\n method: request.method,\n headers: request.headers,\n });\n\n const response = await fetch(requestInit.url, requestInit);\n\n request.reply.status = response.status;\n request.reply.headers = Object.fromEntries(response.headers.entries());\n request.reply.body = response.body;\n\n this.log.debug(\"Received response\", {\n status: request.reply.status,\n headers: request.reply.headers,\n });\n\n if (options.afterResponse) {\n await options.afterResponse(request, response);\n }\n };\n }\n\n private getRawRequestBody(req: ServerRequest): ReadableStream | undefined {\n const { method } = req;\n\n if (method === \"GET\" || method === \"HEAD\" || method === \"OPTIONS\") {\n return;\n }\n\n if (req.raw?.web?.req) {\n return req.raw.web.req.body as ReadableStream;\n }\n\n if (req.raw?.node?.req) {\n const nodeReq = req.raw.node.req;\n return WebStream.from(nodeReq) as ReadableStream;\n }\n }\n}\n","import { $module } from \"alepha\";\nimport { AlephaServer } from \"alepha/server\";\nimport { $proxy } from \"./descriptors/$proxy.ts\";\nimport { ServerProxyProvider } from \"./providers/ServerProxyProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./descriptors/$proxy.ts\";\nexport * from \"./providers/ServerProxyProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Plugin for Alepha that provides a proxy server functionality.\n *\n * @see {@link $proxy}\n * @module alepha.server.proxy\n */\nexport const AlephaServerProxy = $module({\n name: \"alepha.server.proxy\",\n descriptors: [$proxy],\n services: [AlephaServer, ServerProxyProvider],\n});\n","import { $env, $hook, $inject, Alepha, t } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { $retry } from \"alepha/retry\";\nimport type { ServiceAccountDescriptor } from \"alepha/security\";\nimport { ServerProxyProvider } from \"alepha/server/proxy\";\nimport { $remote, type RemoteDescriptor } from \"../descriptors/$remote.ts\";\nimport {\n type ApiLinksResponse,\n apiLinksResponseSchema,\n} from \"../schemas/apiLinksResponseSchema.ts\";\nimport { LinkProvider } from \"./LinkProvider.ts\";\n\nconst envSchema = t.object({\n SERVER_API_PREFIX: t.text({\n description: \"Prefix for all API routes (e.g. $action).\",\n default: \"/api\",\n }),\n});\n\nexport class RemoteDescriptorProvider {\n protected readonly env = $env(envSchema);\n protected readonly alepha = $inject(Alepha);\n protected readonly proxyProvider = $inject(ServerProxyProvider);\n protected readonly linkProvider = $inject(LinkProvider);\n protected readonly remotes: Array<ServerRemote> = [];\n protected readonly log = $logger();\n\n public getRemotes(): ServerRemote[] {\n return this.remotes;\n }\n\n public readonly configure = $hook({\n on: \"configure\",\n handler: async () => {\n const remotes = this.alepha.descriptors($remote);\n for (const remote of remotes) {\n await this.registerRemote(remote);\n }\n },\n });\n\n public readonly start = $hook({\n on: \"start\",\n handler: async () => {\n for (const remote of this.remotes) {\n const token =\n typeof remote.serviceAccount?.token === \"function\"\n ? await remote.serviceAccount.token()\n : undefined;\n\n if (!remote.internal) {\n continue; // skip download links for remotes that are not internal\n }\n\n const { links } = await remote.links({ authorization: token });\n\n for (const link of links) {\n let path = link.path.replace(remote.prefix, \"\");\n if (link.service) {\n path = `/${link.service}${path}`;\n }\n\n this.linkProvider.registerLink({\n ...link,\n prefix: remote.prefix,\n path,\n method: link.method ?? \"GET\",\n host: remote.url,\n service: remote.name,\n });\n }\n\n this.log.info(`Remote '${remote.name}' OK`, {\n links: remote.links.length,\n prefix: remote.prefix,\n });\n }\n },\n });\n\n public async registerRemote(value: RemoteDescriptor): Promise<void> {\n const options = value.options;\n const url = typeof options.url === \"string\" ? options.url : options.url();\n const linkPath = LinkProvider.path.apiLinks;\n const name = value.name;\n const proxy = typeof options.proxy === \"object\" ? options.proxy : {};\n\n const remote: ServerRemote = {\n url,\n name,\n prefix: \"/api\",\n serviceAccount: options.serviceAccount,\n proxy: !!options.proxy,\n internal: !proxy.noInternal,\n schema: async (opts) => {\n const { authorization, name } = opts;\n return await fetch(`${url}${linkPath}/${name}/schema`, {\n headers: new Headers(\n authorization\n ? {\n authorization,\n }\n : {},\n ),\n }).then((it) => it.json()); // TODO: use schema validation for response\n },\n links: async (opts) => {\n const { authorization } = opts;\n const remoteApi = await this.fetchLinks.run({\n service: name,\n url: `${url}${linkPath}`,\n authorization,\n });\n\n if (remoteApi.prefix != null) {\n remote.prefix = remoteApi.prefix; // monkey patch the prefix, not ideal but works\n }\n\n return remoteApi;\n },\n };\n\n this.remotes.push(remote);\n\n if (options.proxy) {\n this.proxyProvider.createProxy({\n path: `${this.env.SERVER_API_PREFIX}/${name}/*`,\n target: url,\n rewrite: (url) => {\n url.pathname = url.pathname.replace(\n `${this.env.SERVER_API_PREFIX}/${name}`,\n remote.prefix,\n );\n },\n ...proxy,\n });\n }\n }\n\n protected readonly fetchLinks = $retry({\n max: 10,\n backoff: {\n initial: 1000,\n },\n onError: (_, attempt, { service, url }) => {\n this.log.warn(`Failed to fetch links, retry (${attempt})...`, {\n service,\n url,\n });\n },\n handler: async (opts: FetchLinksOptions): Promise<ApiLinksResponse> => {\n const { url, authorization } = opts;\n const response = await fetch(url, {\n headers: new Headers(\n authorization\n ? {\n authorization,\n }\n : {},\n ),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch links from ${url}`);\n }\n\n return this.alepha.codec.decode(\n apiLinksResponseSchema,\n await response.json(),\n );\n },\n });\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface FetchLinksOptions {\n /**\n * Name of the remote service.\n */\n service: string;\n\n /**\n * URL to fetch links from.\n */\n url: string;\n\n /**\n * Authorization header containing access token.\n */\n authorization?: string;\n}\n\nexport interface ServerRemote {\n /**\n * URL of the remote service.\n */\n url: string;\n\n /**\n * Name of the remote service.\n */\n name: string;\n\n /**\n * Expose links as endpoint. It's not only internal.\n */\n proxy: boolean;\n\n /**\n * It's only used inside the application.\n */\n internal: boolean;\n\n /**\n * Links fetcher.\n */\n links: (args: { authorization?: string }) => Promise<ApiLinksResponse>;\n\n /**\n * Fetches schema for the remote service.\n */\n schema: (args: { name: string; authorization?: string }) => Promise<any>;\n\n /**\n * Force a default access token provider when not provided.\n */\n serviceAccount?: ServiceAccountDescriptor;\n\n /**\n * Prefix for the remote service links.\n */\n prefix: string;\n}\n","import { $env, $hook, $inject, Alepha, t } from \"alepha\";\nimport {\n type Permission,\n SecurityProvider,\n type UserAccountToken,\n} from \"alepha/security\";\nimport {\n $action,\n $route,\n type ClientRequestEntry,\n type ClientRequestOptions,\n type RequestConfigSchema,\n ServerTimingProvider,\n} from \"alepha/server\";\nimport {\n type ApiLink,\n type ApiLinksResponse,\n apiLinksResponseSchema,\n} from \"../schemas/apiLinksResponseSchema.ts\";\nimport { LinkProvider } from \"./LinkProvider.ts\";\nimport { RemoteDescriptorProvider } from \"./RemoteDescriptorProvider.ts\";\n\nconst envSchema = t.object({\n SERVER_API_PREFIX: t.text({\n description: \"Prefix for all API routes (e.g. $action).\",\n default: \"/api\",\n }),\n});\n\nexport class ServerLinksProvider {\n protected readonly env = $env(envSchema);\n protected readonly alepha = $inject(Alepha);\n protected readonly linkProvider = $inject(LinkProvider);\n protected readonly remoteProvider = $inject(RemoteDescriptorProvider);\n protected readonly serverTimingProvider = $inject(ServerTimingProvider);\n\n public get prefix() {\n return this.env.SERVER_API_PREFIX;\n }\n\n public readonly onRoute = $hook({\n on: \"configure\",\n handler: () => {\n // convert all $action to local links\n for (const action of this.alepha.descriptors($action)) {\n this.linkProvider.registerLink({\n name: action.name,\n group: action.group,\n schema: action.options.schema,\n requestBodyType: action.getBodyContentType(),\n secured: action.options.secure ?? true,\n method: action.method === \"GET\" ? undefined : action.method,\n prefix: action.prefix,\n path: action.path,\n // by local, we mean that it can be called directly via the handler\n handler: (\n config: ClientRequestEntry<RequestConfigSchema>,\n options: ClientRequestOptions = {},\n ) => action.run(config, options),\n });\n }\n },\n });\n\n /**\n * First API - Get all API links for the user.\n *\n * This is based on the user's permissions.\n */\n public readonly links = $route({\n path: LinkProvider.path.apiLinks,\n schema: {\n response: apiLinksResponseSchema,\n },\n handler: ({ user, headers }) => {\n return this.getUserApiLinks({\n user,\n authorization: headers.authorization,\n });\n },\n });\n\n /**\n * Second API - Get schema for a specific API link.\n *\n * Note: Body/Response schema are not included in `links` API because it's TOO BIG.\n * I mean for 150+ links, you got 50ms of serialization time.\n */\n public readonly schema = $route({\n path: LinkProvider.path.apiSchema,\n schema: {\n params: t.object({\n name: t.text(),\n }),\n response: t.json(),\n },\n handler: ({ params, user, headers }) => {\n return this.getSchemaByName(params.name, {\n user,\n authorization: headers.authorization,\n });\n },\n });\n\n public async getSchemaByName(\n name: string,\n options: GetApiLinksOptions = {},\n ): Promise<RequestConfigSchema> {\n const authorization = options.authorization;\n const api = await this.getUserApiLinks({\n user: options.user,\n authorization,\n });\n\n for (const link of api.links) {\n if (link.name === name) {\n if (link.service) {\n // remote\n return this.remoteProvider\n .getRemotes()\n .find((it) => it.name === link.service)\n ?.schema({ name: name, authorization });\n }\n\n // local\n return (\n this.linkProvider.getServerLinks().find((it) => it.name === name)\n ?.schema ?? {}\n );\n }\n }\n\n return {};\n }\n\n /**\n * Retrieves API links for the user based on their permissions.\n * Will check on local links and remote links.\n */\n public async getUserApiLinks(\n options: GetApiLinksOptions,\n ): Promise<ApiLinksResponse> {\n const { user } = options;\n let permissions: Permission[] | undefined;\n let permissionMap: Map<string, Permission> | undefined;\n const hasSecurity = this.alepha.has(SecurityProvider);\n if (hasSecurity && user) {\n permissions = this.alepha.inject(SecurityProvider).getPermissions(user);\n permissionMap = new Map(\n permissions.map((it) => [`${it.group}:${it.name}`, it]),\n );\n }\n\n const userLinks: ApiLink[] = [];\n\n // bonus: add permissions not related to $action\n for (const permission of permissions ?? []) {\n if (\n !permission.path &&\n !permission.method &&\n permission.name &&\n permission.group\n ) {\n userLinks.push({\n path: \"\", // this is a placeholder for links without specific path\n name: permission.name,\n group: permission.group,\n });\n }\n }\n\n // add local links\n for (const link of this.linkProvider.getServerLinks()) {\n // SKIP REMOTE LINKS, remote links are handled separately for security\n if (link.host) continue;\n\n if (hasSecurity && link.secured) {\n // skip secured links if user is not provided\n if (!user) {\n continue;\n }\n\n if (typeof link.secured === \"object\" && link.secured.realm) {\n // realm check\n if (user.realm !== link.secured.realm) {\n continue;\n }\n } else if (permissionMap) {\n // small permissions check, can be optimized later ... :')\n\n if (!permissionMap.has(`${link.group}:${link.name}`)) {\n continue;\n }\n }\n }\n\n userLinks.push({\n name: link.name,\n group: link.group,\n requestBodyType: link.requestBodyType,\n method: link.method,\n path: link.path,\n });\n }\n\n this.serverTimingProvider.beginTiming(\"fetchRemoteLinks\");\n // this does not scale well, but it's working for now\n // TODO: remote links can be cached by user.roles\n const promises = this.remoteProvider\n .getRemotes()\n .filter((it) => it.proxy) // add only \"proxy\" remotes\n .map(async (remote) => {\n const { links, prefix } = await remote.links(options);\n return links.map((link) => {\n let path = link.path.replace(prefix ?? \"/api\", \"\");\n if (link.service) {\n path = `/${link.service}${path}`;\n }\n\n return {\n ...link,\n path,\n proxy: true,\n service: remote.name,\n };\n });\n });\n\n userLinks.push(...(await Promise.all(promises)).flat());\n this.serverTimingProvider.endTiming(\"fetchRemoteLinks\");\n\n return {\n prefix: this.env.SERVER_API_PREFIX,\n links: userLinks,\n };\n }\n}\n\nexport interface GetApiLinksOptions {\n user?: UserAccountToken;\n authorization?: string;\n}\n","import \"alepha/server/security\";\nimport { $module } from \"alepha\";\nimport { AlephaServer } from \"alepha/server\";\nimport { $client } from \"./descriptors/$client.ts\";\nimport { $remote } from \"./descriptors/$remote.ts\";\nimport { LinkProvider } from \"./providers/LinkProvider.ts\";\nimport { RemoteDescriptorProvider } from \"./providers/RemoteDescriptorProvider.ts\";\nimport { ServerLinksProvider } from \"./providers/ServerLinksProvider.ts\";\nimport type { ApiLinksResponse } from \"./schemas/apiLinksResponseSchema.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./descriptors/$client.ts\";\nexport * from \"./descriptors/$remote.ts\";\nexport * from \"./providers/LinkProvider.ts\";\nexport * from \"./providers/RemoteDescriptorProvider.ts\";\nexport * from \"./providers/ServerLinksProvider.ts\";\nexport * from \"./schemas/apiLinksResponseSchema.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha\" {\n interface State {\n /**\n * API links attached to the server request state.\n *\n * @see {@link ApiLinksResponse}\n * @internal\n */\n \"alepha.server.request.apiLinks\"?: ApiLinksResponse;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Provides server-side link management and remote capabilities for client-server interactions.\n *\n * The server-links module enables declarative link definitions using `$remote` and `$client` descriptors,\n * facilitating seamless API endpoint management and client-server communication. It integrates with server\n * security features to ensure safe and controlled access to resources.\n *\n * @see {@link $remote}\n * @see {@link $client}\n * @module alepha.server.links\n */\nexport const AlephaServerLinks = $module({\n name: \"alepha.server.links\",\n descriptors: [$remote, $client],\n services: [\n AlephaServer,\n ServerLinksProvider,\n RemoteDescriptorProvider,\n LinkProvider,\n ],\n});\n","export const alephaServerAuthRoutes = {\n login: \"/oauth/login\",\n callback: \"/oauth/callback\",\n logout: \"/oauth/logout\",\n token: \"/_auth/token\",\n refresh: \"/_auth/refresh\",\n userinfo: \"/_auth/userinfo\",\n};\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const tokensSchema = t.object({\n provider: t.text(),\n access_token: t.text({ size: \"rich\" }),\n issued_at: t.number(),\n expires_in: t.optional(t.number()),\n refresh_token: t.optional(t.text({ size: \"rich\" })),\n refresh_token_expires_in: t.optional(t.number()),\n refresh_expires_in: t.optional(\n t.number({\n description:\n \"Alias of `refresh_token_expires_in` for compatibility with some providers.\",\n }),\n ),\n id_token: t.optional(t.text({ size: \"rich\" })),\n scope: t.optional(t.text()),\n});\n\nexport type Tokens = Static<typeof tokensSchema>;\n","import { type Static, t } from \"alepha\";\nimport { userAccountInfoSchema } from \"alepha/security\";\nimport { apiLinksResponseSchema } from \"alepha/server/links\";\nimport { tokensSchema } from \"./tokensSchema.ts\";\n\nexport const tokenResponseSchema = t.extend(tokensSchema, {\n user: userAccountInfoSchema,\n api: apiLinksResponseSchema,\n});\n\nexport type TokenResponse = Static<typeof tokenResponseSchema>;\n","import { type Static, t } from \"alepha\";\nimport { userAccountInfoSchema } from \"alepha/security\";\nimport { apiLinksResponseSchema } from \"alepha/server/links\";\n\nexport const userinfoResponseSchema = t.object({\n user: t.optional(userAccountInfoSchema),\n api: apiLinksResponseSchema,\n});\n\nexport type UserinfoResponse = Static<typeof userinfoResponseSchema>;\n","import { $hook, $inject, Alepha, t } from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport {\n InvalidCredentialsError,\n SecurityError,\n type UserAccount,\n} from \"alepha/security\";\nimport { $route, BadRequestError } from \"alepha/server\";\nimport {\n $cookie,\n type Cookies,\n ServerCookiesProvider,\n} from \"alepha/server/cookies\";\nimport { ServerLinksProvider } from \"alepha/server/links\";\nimport {\n authorizationCodeGrant,\n buildAuthorizationUrl,\n buildEndSessionUrl,\n calculatePKCECodeChallenge,\n randomPKCECodeVerifier,\n randomState,\n} from \"openid-client\";\nimport { alephaServerAuthRoutes } from \"../constants/routes.ts\";\nimport { $auth, type AuthDescriptor } from \"../descriptors/$auth.ts\";\nimport type { AuthenticationProvider } from \"../schemas/authenticationProviderSchema.ts\";\nimport { tokenResponseSchema } from \"../schemas/tokenResponseSchema.ts\";\nimport { type Tokens, tokensSchema } from \"../schemas/tokensSchema.ts\";\nimport { userinfoResponseSchema } from \"../schemas/userinfoResponseSchema.ts\";\n\nexport class ServerAuthProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly serverCookiesProvider = $inject(ServerCookiesProvider);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly serverLinksProvider = $inject(ServerLinksProvider);\n\n protected readonly authorizationCode = $cookie({\n name: \"authorizationCode\",\n ttl: [15, \"minutes\"],\n httpOnly: true,\n schema: t.object({\n provider: t.text(),\n codeVerifier: t.optional(t.text({ size: \"long\" })),\n redirectUri: t.optional(t.text({ size: \"long\" })),\n state: t.optional(t.text()),\n nonce: t.optional(t.text()),\n }),\n });\n\n public readonly tokens = $cookie({\n name: \"tokens\",\n ttl: [30, \"days\"],\n httpOnly: true,\n compress: true,\n encrypt: true,\n schema: tokensSchema,\n });\n\n public get identities(): Array<AuthDescriptor> {\n return this.alepha\n .descriptors($auth)\n .filter((auth) => !auth.options.disabled);\n }\n\n public getAuthenticationProviders(\n filters: { realmName?: string } = {},\n ): AuthenticationProvider[] {\n const providers: AuthenticationProvider[] = [];\n\n for (const identity of this.identities) {\n if (filters.realmName) {\n const realm = \"realm\" in identity.options && identity.options.realm;\n if (!realm || realm.name !== filters.realmName) {\n continue;\n }\n }\n\n const type =\n \"oidc\" in identity.options\n ? \"OIDC\"\n : \"oauth\" in identity.options\n ? \"OAUTH2\"\n : \"credentials\" in identity.options\n ? \"CREDENTIALS\"\n : undefined;\n\n if (!type) {\n continue;\n }\n\n providers.push({\n name: identity.name,\n type,\n });\n }\n\n return providers;\n }\n\n protected readonly configure = $hook({\n on: \"configure\",\n handler: async () => {\n for (const identity of this.identities) {\n await identity.prepare();\n }\n },\n });\n\n protected getAccessTokens(tokens: Tokens) {\n const idp = this.provider(tokens.provider);\n\n if (\n \"oidc\" in idp.options &&\n !(\"realm\" in idp.options) &&\n idp.options.oidc?.useIdToken\n ) {\n return tokens.id_token;\n }\n\n return tokens.access_token;\n }\n\n /**\n * Fill request headers with access token from cookies or fallback to provider's fallback function.\n */\n protected readonly onRequest = $hook({\n on: \"server:onRequest\",\n after: this.serverCookiesProvider,\n handler: async ({ request }) => {\n const cookies = request.cookies;\n\n // [feature] forward cookies to request headers\n if (cookies) {\n const tokens = await this.cookiesToTokens(cookies);\n if (tokens) {\n request.headers.authorization = `Bearer ${this.getAccessTokens(tokens)}`;\n this.log.trace(\"Access token set in request headers\", {\n provider: tokens.provider,\n });\n }\n }\n\n // [feature] support for auth providers with fallback\n if (!request.headers.authorization) {\n for (const provider of this.identities) {\n if (!(\"realm\" in provider.options) && !!provider.options.fallback) {\n const token = await provider.options.fallback();\n if (token) {\n request.headers.authorization = `Bearer ${token}`;\n break;\n }\n }\n }\n }\n },\n });\n\n /**\n * Convert cookies to tokens.\n * If the tokens are expired, try to refresh them using the refresh token.\n */\n protected async cookiesToTokens(\n cookies: Cookies,\n ): Promise<Tokens | undefined> {\n const tokens = this.tokens.get({ cookies });\n if (!tokens) {\n // no cookie, no tokens\n this.log.trace(\"No tokens found in cookies\");\n return;\n }\n\n this.log.trace(\"Tokens found in cookies\", {\n expires_in: tokens.expires_in,\n issued_at: tokens.issued_at,\n });\n\n // check if tokens are expired\n const refreshedTokens = await this.refreshTokens(tokens);\n if (!refreshedTokens) {\n this.tokens.del({ cookies });\n // 08/25: exception here will go to Server error handler, not the React one\n // better to remove cookie & session and let the page handle 401 Unauthorized\n //throw new SessionExpiredError(\"Session expired. Please login again.\");\n return;\n }\n\n if (refreshedTokens.access_token !== tokens.access_token) {\n this.setTokens(refreshedTokens, cookies);\n }\n\n return refreshedTokens;\n }\n\n protected async refreshTokens(tokens: Tokens): Promise<Tokens | undefined> {\n if (tokens.expires_in && tokens.issued_at) {\n const gracePeriodSec = 10;\n const expiresAt = tokens.issued_at + (tokens.expires_in - gracePeriodSec);\n\n if (expiresAt < this.dateTimeProvider.now().unix()) {\n this.log.trace(\"Tokens are expired\");\n\n // oh no, it is expired\n if (tokens.refresh_token) {\n this.log.trace(\"Trying to refresh tokens using refresh token\");\n // but has refresh token!\n try {\n const provider = this.provider(tokens);\n const result = await provider.refresh(\n tokens.refresh_token,\n tokens.access_token,\n );\n const newTokens = {\n ...result,\n provider: tokens.provider,\n issued_at: this.dateTimeProvider.now().unix(),\n };\n\n this.log.debug(\"Tokens refreshed successfully\");\n\n return newTokens;\n } catch (e) {\n this.log.warn(\"Failed to refresh token\", e);\n }\n }\n\n // session expired and no (valid) refresh token\n return;\n }\n }\n\n if (!tokens.issued_at && tokens.access_token) {\n return;\n }\n\n return tokens;\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Get user information.\n */\n public readonly userinfo = $route({\n path: alephaServerAuthRoutes.userinfo,\n schema: {\n response: userinfoResponseSchema,\n },\n handler: async ({ user, headers, cookies }) => {\n const tokens = this.tokens.get({ cookies });\n if (tokens) {\n const provider = this.provider(tokens);\n if (!(\"realm\" in provider.options)) {\n const user = await provider.user(tokens);\n const api = await this.serverLinksProvider.getUserApiLinks({\n authorization: headers.authorization,\n user,\n });\n return {\n api,\n user,\n };\n }\n }\n\n const api = await this.serverLinksProvider.getUserApiLinks({\n authorization: headers.authorization,\n user,\n });\n\n return {\n api,\n user,\n };\n },\n });\n\n /**\n * Refresh a token for internal providers.\n */\n public readonly refresh = $route({\n path: alephaServerAuthRoutes.refresh,\n method: \"POST\",\n schema: {\n query: t.object({\n provider: t.text(),\n }),\n body: t.object({\n refresh_token: t.text({\n size: \"rich\",\n }),\n access_token: t.optional(\n t.text({\n size: \"rich\",\n description:\n \"Required if provider has stateless refresh token on credentials mode\",\n }),\n ),\n }),\n response: tokensSchema,\n },\n handler: async ({ query, body, cookies }) => {\n const provider = this.provider(query);\n\n const tokens = {\n provider: query.provider,\n ...(await provider.refresh(body.refresh_token, body.access_token)),\n };\n\n // for web applications, we store tokens in cookies\n this.setTokens(tokens, cookies);\n\n return tokens;\n },\n });\n\n /**\n * Login for local password-based authentication.\n */\n public readonly token = $route({\n path: alephaServerAuthRoutes.token,\n method: \"POST\",\n schema: {\n query: t.object({\n provider: t.text(),\n }),\n body: t.object({\n username: t.text(),\n password: t.text(),\n }),\n response: tokenResponseSchema,\n },\n handler: async ({ query, body, cookies }) => {\n const provider = this.provider(query);\n const realm = \"realm\" in provider.options && provider.options.realm;\n if (!realm) {\n throw new SecurityError(\n `Auth provider '${query.provider}' does not support password grant`,\n );\n }\n\n const credentials =\n \"credentials\" in provider.options && provider.options.credentials;\n\n if (!credentials) {\n throw new SecurityError(\n `Auth provider '${query.provider}' does not support password grant`,\n );\n }\n\n let user: UserAccount | undefined;\n try {\n user = await credentials.account(body);\n } catch (e) {\n if (e instanceof InvalidCredentialsError) {\n throw e;\n }\n this.log.error(\"Failed to authenticate user\", e);\n throw new InvalidCredentialsError();\n }\n\n if (!user) {\n throw new InvalidCredentialsError();\n }\n\n const tokens = {\n provider: query.provider,\n ...(await realm.createToken(user)),\n };\n\n // for web applications, we store tokens in cookies\n this.setTokens(tokens, cookies);\n\n const api = await this.serverLinksProvider.getUserApiLinks({\n user,\n });\n\n // mobile apps require this\n return {\n ...tokens,\n user,\n api,\n };\n },\n });\n\n /**\n * Oauth2/OIDC login route.\n */\n public readonly login = $route({\n path: alephaServerAuthRoutes.login,\n schema: {\n query: t.object({\n provider: t.text(),\n redirect_uri: t.optional(t.text({ size: \"rich\" })),\n }),\n },\n handler: async ({ query, url, reply }) => {\n const provider = this.provider(query);\n const oauth = provider.oauth;\n if (!oauth) {\n throw new SecurityError(\n `Auth provider '${query.provider}' does not support OAuth2`,\n );\n }\n\n const scope = provider.scope;\n let redirect_uri =\n provider.redirect_uri || alephaServerAuthRoutes.callback;\n if (redirect_uri.startsWith(\"/\")) {\n redirect_uri = `${url.protocol}//${url.host}${redirect_uri}`;\n }\n\n const oidc = \"oidc\" in provider.options && provider.options.oidc;\n\n if (!oauth.serverMetadata().supportsPKCE()) {\n const state = randomState();\n const parameters: Record<string, string> = {\n redirect_uri,\n state,\n };\n\n if (oidc) {\n parameters.nonce = randomState();\n }\n\n if (scope) {\n parameters.scope = scope;\n }\n\n this.authorizationCode.set({\n state,\n nonce: parameters.nonce,\n redirectUri: query.redirect_uri ?? \"/\",\n provider: query.provider,\n });\n\n reply.redirect(buildAuthorizationUrl(oauth, parameters).toString());\n return;\n }\n\n const codeVerifier = randomPKCECodeVerifier();\n const codeChallenge = await calculatePKCECodeChallenge(codeVerifier);\n\n const parameters: Record<string, string> = {\n redirect_uri,\n code_challenge: codeChallenge,\n code_challenge_method: \"S256\",\n };\n\n if (scope) {\n parameters.scope = scope;\n }\n\n this.authorizationCode.set({\n codeVerifier,\n redirectUri: query.redirect_uri ?? \"/\",\n provider: query.provider,\n });\n\n reply.redirect(buildAuthorizationUrl(oauth, parameters).toString());\n },\n });\n\n /**\n * Callback for OAuth2/OIDC providers.\n * It handles the authorization code flow and retrieves the access token.\n */\n public readonly callback = $route({\n path: alephaServerAuthRoutes.callback,\n handler: async ({ url, reply, cookies }) => {\n const authorizationCode = this.authorizationCode.get({ cookies });\n if (!authorizationCode) {\n throw new BadRequestError(\"Missing code verifier\");\n }\n\n const provider = this.provider(authorizationCode);\n const oauth = provider.oauth;\n if (!oauth) {\n throw new SecurityError(\n `Auth provider '${provider.name}' does not support OAuth2`,\n );\n }\n\n const redirectUri = authorizationCode.redirectUri ?? \"/\";\n\n const externalTokens = await authorizationCodeGrant(oauth, url, {\n pkceCodeVerifier: authorizationCode.codeVerifier,\n expectedState: authorizationCode.state,\n expectedNonce: authorizationCode.nonce,\n })\n .then((tokens) => ({\n issued_at: this.dateTimeProvider.now().unix(),\n provider: provider.name,\n ...tokens,\n }))\n .catch((e) => {\n this.log.error(\"Failed to get access token\", e);\n throw new SecurityError(\"Failed to get access token\", {\n cause: e,\n });\n });\n\n this.authorizationCode.del({ cookies });\n\n const realm = \"realm\" in provider.options && provider.options.realm;\n\n // external, full OIDC System (e.g. Keycloak, Auth0)\n if (!realm) {\n this.setTokens(externalTokens, cookies);\n reply.redirect(redirectUri);\n return;\n }\n\n // internal, we need to create our own tokens\n\n const user = await provider.user(externalTokens);\n const tokens = await realm.createToken(user);\n\n this.setTokens(\n {\n ...tokens,\n issued_at: this.dateTimeProvider.now().unix(),\n provider: provider.name,\n },\n cookies,\n );\n\n reply.redirect(redirectUri);\n },\n });\n\n /**\n * Logout route for OAuth2/OIDC providers.\n */\n public readonly logout = $route({\n path: alephaServerAuthRoutes.logout,\n method: \"GET\",\n schema: {\n query: t.object({\n post_logout_redirect_uri: t.optional(t.text()),\n }),\n },\n handler: async ({ query, reply, cookies }) => {\n const redirect = query.post_logout_redirect_uri ?? \"/\";\n const tokens = this.tokens.get({ cookies });\n if (!tokens) {\n reply.redirect(redirect);\n return;\n }\n\n const provider = this.provider(tokens.provider);\n\n this.tokens.del({ cookies });\n\n // for internal providers, we can delete the session - if available\n if (\"realm\" in provider.options && tokens.refresh_token) {\n const onDeleteSession =\n provider.options.realm.options.settings?.onDeleteSession;\n if (onDeleteSession) {\n try {\n await onDeleteSession(tokens.refresh_token);\n } catch (e) {\n this.log.error(\"Failed to delete session\", e);\n }\n }\n }\n\n const oauth = provider.oauth;\n if (!oauth) {\n reply.redirect(redirect);\n return;\n }\n\n const params = new URLSearchParams();\n const idToken = tokens?.id_token;\n\n params.set(\"post_logout_redirect_uri\", redirect);\n if (idToken) {\n params.set(\"id_token_hint\", idToken);\n }\n\n const customLogoutUri =\n \"oidc\" in provider.options\n ? provider.options.oidc?.logoutUri\n : undefined;\n\n if (customLogoutUri) {\n reply.redirect(`${customLogoutUri}?${params}`);\n return;\n }\n\n if (!oauth.serverMetadata().end_session_endpoint) {\n // await tokenRevocation(\n // \toauth,\n // \ttokens?.refresh_token ?? tokens.access_token,\n // );\n reply.redirect(redirect);\n return;\n }\n\n reply.redirect(buildEndSessionUrl(oauth, params).toString());\n },\n });\n\n protected provider(opts: string | { provider: string }): AuthDescriptor {\n const name = typeof opts === \"string\" ? opts : opts.provider;\n const identity = this.identities.find((identity) => identity.name === name);\n\n if (!identity) {\n throw new SecurityError(`Auth provider '${name}' not found`);\n }\n\n return identity;\n }\n\n protected setTokens(tokens: Tokens, cookies?: Cookies): void {\n const exp =\n tokens.refresh_token_expires_in ||\n tokens.refresh_expires_in ||\n tokens.expires_in;\n\n const ttl = exp\n ? this.dateTimeProvider.duration(exp, \"seconds\")\n : undefined;\n\n this.tokens.set(tokens, {\n cookies,\n ttl,\n });\n }\n}\n\nexport interface OAuth2Profile {\n sub: string; // Subject - unique ID per user (required by OpenID)\n email?: string;\n name?: string;\n given_name?: string;\n family_name?: string;\n middle_name?: string;\n nickname?: string;\n preferred_username?: string;\n profile?: string;\n picture?: string;\n website?: string;\n email_verified?: boolean;\n gender?: string;\n birthdate?: string; // ISO 8601: YYYY-MM-DD\n zoneinfo?: string;\n locale?: string;\n phone_number?: string;\n phone_number_verified?: boolean;\n address?: {\n formatted?: string;\n street_address?: string;\n locality?: string;\n region?: string;\n postal_code?: string;\n country?: string;\n };\n updated_at?: number; // seconds since epoch\n // Allow additional fields (provider-specific)\n [key: string]: unknown;\n}\n","import { AlephaError } from \"alepha\";\nimport type { RealmDescriptor } from \"alepha/security\";\nimport {\n $auth,\n type CredentialsFn,\n type CredentialsOptions,\n type WithLoginFn,\n} from \"./$auth.ts\";\n\n/**\n * Already configured Credentials authentication descriptor.\n *\n * Uses username and password to authenticate users.\n */\nexport const $authCredentials = (\n realm: RealmDescriptor & WithLoginFn,\n options: Partial<CredentialsOptions> = {},\n) => {\n const name = \"credentials\";\n\n const account: CredentialsFn | undefined = realm.login\n ? realm.login(name)\n : options.account;\n\n if (!account) {\n throw new AlephaError(\n \"Credentials authentication requires a login function in the realm descriptor.\",\n );\n }\n\n return $auth({\n realm,\n name,\n credentials: {\n account,\n },\n });\n};\n","import { $context, AlephaError, t } from \"alepha\";\nimport type { RealmDescriptor } from \"alepha/security\";\nimport type { OAuth2Profile } from \"../providers/ServerAuthProvider.ts\";\nimport {\n $auth,\n type LinkAccountFn,\n type OidcOptions,\n type WithLinkFn,\n} from \"./$auth.ts\";\n\n/**\n * Already configured GitHub authentication descriptor.\n *\n * Uses OAuth2 to authenticate users via their GitHub accounts.\n * Upon successful authentication, it links the GitHub account to a user session.\n *\n * Environment Variables:\n * - `GITHUB_CLIENT_ID`: The client ID obtained from the GitHub Developer Settings.\n * - `GITHUB_CLIENT_SECRET`: The client secret obtained from the GitHub Developer Settings.\n */\nexport const $authGithub = (\n realm: RealmDescriptor & WithLinkFn,\n options: Partial<OidcOptions> = {},\n) => {\n const { alepha } = $context();\n\n const env = alepha.parseEnv(\n t.object({\n GITHUB_CLIENT_ID: t.optional(t.text()),\n GITHUB_CLIENT_SECRET: t.optional(t.text()),\n }),\n );\n\n const disabled = !env.GITHUB_CLIENT_ID || !env.GITHUB_CLIENT_SECRET;\n\n const name = \"github\";\n\n const account: LinkAccountFn | undefined =\n options.account ?? (realm.link ? realm.link(name) : undefined);\n\n if (!account) {\n throw new AlephaError(\n \"Authentication requires a link function in the realm descriptor.\",\n );\n }\n\n return $auth({\n realm,\n name,\n oauth: {\n clientId: env.GITHUB_CLIENT_ID!,\n clientSecret: env.GITHUB_CLIENT_SECRET!,\n authorization: \"https://github.com/login/oauth/authorize\",\n token: \"https://github.com/login/oauth/access_token\",\n scope: \"read:user user:email\",\n userinfo: async (tokens) => {\n const BASE_URL = \"https://api.github.com\";\n const res = await fetch(`${BASE_URL}/user`, {\n headers: {\n Authorization: `Bearer ${tokens.access_token}`,\n \"User-Agent\": \"Alepha\",\n },\n }).then((res) => res.json());\n\n const user: OAuth2Profile = {\n sub: res.id.toString(),\n };\n\n if (res.email) {\n user.email = res.email;\n }\n\n if (res.name) {\n user.name = res.name.trim();\n }\n\n if (res.avatar_url) {\n user.picture = res.avatar_url;\n }\n\n if (!user.email) {\n const res = await fetch(`${BASE_URL}/user/emails`, {\n headers: {\n Authorization: `Bearer ${tokens.access_token}`,\n \"User-Agent\": \"Alepha\",\n },\n });\n if (res.ok) {\n const emails: any[] = await res.json();\n user.email = (emails.find((e) => e.primary) ?? emails[0]).email;\n }\n }\n\n return user;\n },\n ...options,\n account,\n },\n disabled,\n });\n};\n","import { $context, AlephaError, t } from \"alepha\";\nimport type { RealmDescriptor } from \"alepha/security\";\nimport {\n $auth,\n type LinkAccountFn,\n type OidcOptions,\n type WithLinkFn,\n} from \"./$auth.ts\";\n\n/**\n * Already configured Google authentication descriptor.\n *\n * Uses OpenID Connect (OIDC) to authenticate users via their Google accounts.\n * Upon successful authentication, it links the Google account to a user session.\n *\n * Environment Variables:\n * - `GOOGLE_CLIENT_ID`: The client ID obtained from the Google Developer Console.\n * - `GOOGLE_CLIENT_SECRET`: The client secret obtained from the Google Developer Console.\n */\nexport const $authGoogle = (\n realm: RealmDescriptor & WithLinkFn,\n options: Partial<OidcOptions> = {},\n) => {\n const { alepha } = $context();\n\n const env = alepha.parseEnv(\n t.object({\n GOOGLE_CLIENT_ID: t.optional(t.text()),\n GOOGLE_CLIENT_SECRET: t.optional(t.text()),\n }),\n );\n\n const disabled = !env.GOOGLE_CLIENT_ID || !env.GOOGLE_CLIENT_SECRET;\n\n const name = \"google\";\n\n const account: LinkAccountFn | undefined =\n options.account ?? (realm.link ? realm.link(name) : undefined);\n\n if (!account) {\n throw new AlephaError(\n \"Authentication requires a link function in the realm descriptor.\",\n );\n }\n\n return $auth({\n realm,\n name,\n oidc: {\n issuer: \"https://accounts.google.com\",\n clientId: env.GOOGLE_CLIENT_ID!,\n clientSecret: env.GOOGLE_CLIENT_SECRET,\n ...options,\n account,\n },\n disabled,\n });\n};\n","import { type Static, t } from \"alepha\";\n\nexport const authenticationProviderSchema = t.object(\n {\n name: t.text({\n description: \"Name of the authentication provider.\",\n }),\n type: t.enum([\"OAUTH2\", \"OIDC\", \"CREDENTIALS\"], {\n description: \"Type of the authentication provider.\",\n }),\n },\n {\n title: \"AuthenticationProvider\",\n },\n);\n\nexport type AuthenticationProvider = Static<\n typeof authenticationProviderSchema\n>;\n","import { $module } from \"alepha\";\nimport type { UserAccount } from \"alepha/security\";\nimport { AlephaServerCookies } from \"alepha/server/cookies\";\nimport { $auth } from \"./descriptors/$auth.ts\";\nimport { ServerAuthProvider } from \"./providers/ServerAuthProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./descriptors/$auth.ts\";\nexport * from \"./descriptors/$authCredentials.ts\";\nexport * from \"./descriptors/$authGithub.ts\";\nexport * from \"./descriptors/$authGoogle.ts\";\nexport * from \"./index.shared.ts\";\nexport * from \"./providers/ServerAuthProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha\" {\n export interface State {\n /**\n * The authenticated user account attached to the server request state.\n *\n * @internal\n */\n \"alepha.server.request.user\"?: UserAccount;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Allow authentication services for server applications.\n * It provides login and logout functionalities.\n *\n * There are multiple authentication providers available (e.g., Google, GitHub).\n * You can also delegate authentication to your own OIDC/OAuth2, for example using Keycloak or Auth0.\n *\n * It's cookie-based and SSR friendly.\n *\n * @see {@link $auth}\n * @see {@link ServerAuthProvider}\n * @module alepha.server.auth\n */\nexport const AlephaServerAuth = $module({\n name: \"alepha.server.auth\",\n descriptors: [$auth],\n services: [AlephaServerCookies, ServerAuthProvider],\n});\n"],"x_google_ignoreList":[4,5],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["USER_AGENT","ERR_INVALID_ARG_VALUE","ERR_INVALID_ARG_TYPE","CodedTypeError","allowInsecureRequests","clockSkew","clockTolerance","customFetch","modifyAssertion","decoder","headers","signal","performDiscovery","assertString","calculatePKCECodeChallenge","ClientSecretPost","None","skipSubjectCheck","skipStateCheck","oauth.ClientSecretPost","headers","oauth.None","oauth.skipStateCheck","oauth.skipSubjectCheck","oauth.customFetch","oauth.modifyAssertion","oauth.clockSkew","oauth.clockTolerance","oauth.calculatePKCECodeChallenge","oauth.generateRandomCodeVerifier","oauth.generateRandomState","oauth.ResponseBodyError","oauth.AuthorizationResponseError","oauth.WWWAuthenticateChallengeError","oauth.OperationProcessingError","oauth.HTTP_REQUEST_FORBIDDEN","oauth.REQUEST_PROTOCOL_FORBIDDEN","oauth.RESPONSE_IS_NOT_CONFORM","oauth.RESPONSE_IS_NOT_JSON","oauth.PARSE_ERROR","oauth.INVALID_RESPONSE","oauth.JWT_CLAIM_COMPARISON","oauth.JSON_ATTRIBUTE_COMPARISON","oauth.JWT_TIMESTAMP_CHECK","oauth.UnsupportedOperationError","oauth.UNSUPPORTED_OPERATION","signal","oauth.discoveryRequest","oauth.allowInsecureRequests","oauth.processDiscoveryResponse","oauth._nodiscoverycheck","oauth._expectedIssuer","oauth.getValidatedIdTokenClaims","oauth.formPostResponse","oauth.validateAuthResponse","oauth\n .authorizationCodeGrantRequest","oauth.nopkce","fetch","oauth.processAuthorizationCodeResponse","oauth.jweDecrypt","oauth\n .refreshTokenGrantRequest","oauth.processRefreshTokenResponse","oauth.resolveEndpoint","oauth.isDPoPNonceError","addons: Array<(config: Configuration) => void>","providers: AuthenticationProvider[]","e","user","headers","user: UserAccount | undefined","parameters: Record<string, string>","parameters","tokens","identity","account: CredentialsFn | undefined","account: LinkAccountFn | undefined","res","user: OAuth2Profile","emails: any[]","e","account: LinkAccountFn | undefined"],"sources":["../../../../node_modules/oauth4webapi/build/index.js","../../../../node_modules/openid-client/build/index.js","../../src/server-auth/primitives/$auth.ts","../../src/server-auth/constants/routes.ts","../../src/server-auth/schemas/tokensSchema.ts","../../src/server-auth/schemas/tokenResponseSchema.ts","../../src/server-auth/schemas/userinfoResponseSchema.ts","../../src/server-auth/providers/ServerAuthProvider.ts","../../src/server-auth/schemas/authenticationProviderSchema.ts","../../src/server-auth/primitives/$authCredentials.ts","../../src/server-auth/primitives/$authGithub.ts","../../src/server-auth/primitives/$authGoogle.ts","../../src/server-auth/index.ts"],"sourcesContent":["let USER_AGENT;\nif (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {\n const NAME = 'oauth4webapi';\n const VERSION = 'v3.8.3';\n USER_AGENT = `${NAME}/${VERSION}`;\n}\nfunction looseInstanceOf(input, expected) {\n if (input == null) {\n return false;\n }\n try {\n return (input instanceof expected ||\n Object.getPrototypeOf(input)[Symbol.toStringTag] === expected.prototype[Symbol.toStringTag]);\n }\n catch {\n return false;\n }\n}\nconst ERR_INVALID_ARG_VALUE = 'ERR_INVALID_ARG_VALUE';\nconst ERR_INVALID_ARG_TYPE = 'ERR_INVALID_ARG_TYPE';\nfunction CodedTypeError(message, code, cause) {\n const err = new TypeError(message, { cause });\n Object.assign(err, { code });\n return err;\n}\nexport const allowInsecureRequests = Symbol();\nexport const clockSkew = Symbol();\nexport const clockTolerance = Symbol();\nexport const customFetch = Symbol();\nexport const modifyAssertion = Symbol();\nexport const jweDecrypt = Symbol();\nexport const jwksCache = Symbol();\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\nfunction buf(input) {\n if (typeof input === 'string') {\n return encoder.encode(input);\n }\n return decoder.decode(input);\n}\nlet encodeBase64Url;\nif (Uint8Array.prototype.toBase64) {\n encodeBase64Url = (input) => {\n if (input instanceof ArrayBuffer) {\n input = new Uint8Array(input);\n }\n return input.toBase64({ alphabet: 'base64url', omitPadding: true });\n };\n}\nelse {\n const CHUNK_SIZE = 0x8000;\n encodeBase64Url = (input) => {\n if (input instanceof ArrayBuffer) {\n input = new Uint8Array(input);\n }\n const arr = [];\n for (let i = 0; i < input.byteLength; i += CHUNK_SIZE) {\n arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));\n }\n return btoa(arr.join('')).replace(/=/g, '').replace(/\\+/g, '-').replace(/\\//g, '_');\n };\n}\nlet decodeBase64Url;\nif (Uint8Array.fromBase64) {\n decodeBase64Url = (input) => {\n try {\n return Uint8Array.fromBase64(input, { alphabet: 'base64url' });\n }\n catch (cause) {\n throw CodedTypeError('The input to be decoded is not correctly encoded.', ERR_INVALID_ARG_VALUE, cause);\n }\n };\n}\nelse {\n decodeBase64Url = (input) => {\n try {\n const binary = atob(input.replace(/-/g, '+').replace(/_/g, '/').replace(/\\s/g, ''));\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n }\n catch (cause) {\n throw CodedTypeError('The input to be decoded is not correctly encoded.', ERR_INVALID_ARG_VALUE, cause);\n }\n };\n}\nfunction b64u(input) {\n if (typeof input === 'string') {\n return decodeBase64Url(input);\n }\n return encodeBase64Url(input);\n}\nexport class UnsupportedOperationError extends Error {\n code;\n constructor(message, options) {\n super(message, options);\n this.name = this.constructor.name;\n this.code = UNSUPPORTED_OPERATION;\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nexport class OperationProcessingError extends Error {\n code;\n constructor(message, options) {\n super(message, options);\n this.name = this.constructor.name;\n if (options?.code) {\n this.code = options?.code;\n }\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nfunction OPE(message, code, cause) {\n return new OperationProcessingError(message, { code, cause });\n}\nasync function calculateJwkThumbprint(jwk) {\n let components;\n switch (jwk.kty) {\n case 'EC':\n components = {\n crv: jwk.crv,\n kty: jwk.kty,\n x: jwk.x,\n y: jwk.y,\n };\n break;\n case 'OKP':\n components = {\n crv: jwk.crv,\n kty: jwk.kty,\n x: jwk.x,\n };\n break;\n case 'AKP':\n components = {\n alg: jwk.alg,\n kty: jwk.kty,\n pub: jwk.pub,\n };\n break;\n case 'RSA':\n components = {\n e: jwk.e,\n kty: jwk.kty,\n n: jwk.n,\n };\n break;\n default:\n throw new UnsupportedOperationError('unsupported JWK key type', { cause: jwk });\n }\n return b64u(await crypto.subtle.digest('SHA-256', buf(JSON.stringify(components))));\n}\nfunction assertCryptoKey(key, it) {\n if (!(key instanceof CryptoKey)) {\n throw CodedTypeError(`${it} must be a CryptoKey`, ERR_INVALID_ARG_TYPE);\n }\n}\nfunction assertPrivateKey(key, it) {\n assertCryptoKey(key, it);\n if (key.type !== 'private') {\n throw CodedTypeError(`${it} must be a private CryptoKey`, ERR_INVALID_ARG_VALUE);\n }\n}\nfunction assertPublicKey(key, it) {\n assertCryptoKey(key, it);\n if (key.type !== 'public') {\n throw CodedTypeError(`${it} must be a public CryptoKey`, ERR_INVALID_ARG_VALUE);\n }\n}\nfunction normalizeTyp(value) {\n return value.toLowerCase().replace(/^application\\//, '');\n}\nfunction isJsonObject(input) {\n if (input === null || typeof input !== 'object' || Array.isArray(input)) {\n return false;\n }\n return true;\n}\nfunction prepareHeaders(input) {\n if (looseInstanceOf(input, Headers)) {\n input = Object.fromEntries(input.entries());\n }\n const headers = new Headers(input ?? {});\n if (USER_AGENT && !headers.has('user-agent')) {\n headers.set('user-agent', USER_AGENT);\n }\n if (headers.has('authorization')) {\n throw CodedTypeError('\"options.headers\" must not include the \"authorization\" header name', ERR_INVALID_ARG_VALUE);\n }\n return headers;\n}\nfunction signal(url, value) {\n if (value !== undefined) {\n if (typeof value === 'function') {\n value = value(url.href);\n }\n if (!(value instanceof AbortSignal)) {\n throw CodedTypeError('\"options.signal\" must return or be an instance of AbortSignal', ERR_INVALID_ARG_TYPE);\n }\n return value;\n }\n return undefined;\n}\nfunction replaceDoubleSlash(pathname) {\n if (pathname.includes('//')) {\n return pathname.replace('//', '/');\n }\n return pathname;\n}\nfunction prependWellKnown(url, wellKnown, allowTerminatingSlash = false) {\n if (url.pathname === '/') {\n url.pathname = wellKnown;\n }\n else {\n url.pathname = replaceDoubleSlash(`${wellKnown}/${allowTerminatingSlash ? url.pathname : url.pathname.replace(/(\\/)$/, '')}`);\n }\n return url;\n}\nfunction appendWellKnown(url, wellKnown) {\n url.pathname = replaceDoubleSlash(`${url.pathname}/${wellKnown}`);\n return url;\n}\nasync function performDiscovery(input, urlName, transform, options) {\n if (!(input instanceof URL)) {\n throw CodedTypeError(`\"${urlName}\" must be an instance of URL`, ERR_INVALID_ARG_TYPE);\n }\n checkProtocol(input, options?.[allowInsecureRequests] !== true);\n const url = transform(new URL(input.href));\n const headers = prepareHeaders(options?.headers);\n headers.set('accept', 'application/json');\n return (options?.[customFetch] || fetch)(url.href, {\n body: undefined,\n headers: Object.fromEntries(headers.entries()),\n method: 'GET',\n redirect: 'manual',\n signal: signal(url, options?.signal),\n });\n}\nexport async function discoveryRequest(issuerIdentifier, options) {\n return performDiscovery(issuerIdentifier, 'issuerIdentifier', (url) => {\n switch (options?.algorithm) {\n case undefined:\n case 'oidc':\n appendWellKnown(url, '.well-known/openid-configuration');\n break;\n case 'oauth2':\n prependWellKnown(url, '.well-known/oauth-authorization-server');\n break;\n default:\n throw CodedTypeError('\"options.algorithm\" must be \"oidc\" (default), or \"oauth2\"', ERR_INVALID_ARG_VALUE);\n }\n return url;\n }, options);\n}\nfunction assertNumber(input, allow0, it, code, cause) {\n try {\n if (typeof input !== 'number' || !Number.isFinite(input)) {\n throw CodedTypeError(`${it} must be a number`, ERR_INVALID_ARG_TYPE, cause);\n }\n if (input > 0)\n return;\n if (allow0) {\n if (input !== 0) {\n throw CodedTypeError(`${it} must be a non-negative number`, ERR_INVALID_ARG_VALUE, cause);\n }\n return;\n }\n throw CodedTypeError(`${it} must be a positive number`, ERR_INVALID_ARG_VALUE, cause);\n }\n catch (err) {\n if (code) {\n throw OPE(err.message, code, cause);\n }\n throw err;\n }\n}\nfunction assertString(input, it, code, cause) {\n try {\n if (typeof input !== 'string') {\n throw CodedTypeError(`${it} must be a string`, ERR_INVALID_ARG_TYPE, cause);\n }\n if (input.length === 0) {\n throw CodedTypeError(`${it} must not be empty`, ERR_INVALID_ARG_VALUE, cause);\n }\n }\n catch (err) {\n if (code) {\n throw OPE(err.message, code, cause);\n }\n throw err;\n }\n}\nexport async function processDiscoveryResponse(expectedIssuerIdentifier, response) {\n const expected = expectedIssuerIdentifier;\n if (!(expected instanceof URL) && expected !== _nodiscoverycheck) {\n throw CodedTypeError('\"expectedIssuerIdentifier\" must be an instance of URL', ERR_INVALID_ARG_TYPE);\n }\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n if (response.status !== 200) {\n throw OPE('\"response\" is not a conform Authorization Server Metadata response (unexpected HTTP status code)', RESPONSE_IS_NOT_CONFORM, response);\n }\n assertReadableResponse(response);\n const json = await getResponseJsonBody(response);\n assertString(json.issuer, '\"response\" body \"issuer\" property', INVALID_RESPONSE, { body: json });\n if (expected !== _nodiscoverycheck && new URL(json.issuer).href !== expected.href) {\n throw OPE('\"response\" body \"issuer\" property does not match the expected value', JSON_ATTRIBUTE_COMPARISON, { expected: expected.href, body: json, attribute: 'issuer' });\n }\n return json;\n}\nfunction assertApplicationJson(response) {\n assertContentType(response, 'application/json');\n}\nfunction notJson(response, ...types) {\n let msg = '\"response\" content-type must be ';\n if (types.length > 2) {\n const last = types.pop();\n msg += `${types.join(', ')}, or ${last}`;\n }\n else if (types.length === 2) {\n msg += `${types[0]} or ${types[1]}`;\n }\n else {\n msg += types[0];\n }\n return OPE(msg, RESPONSE_IS_NOT_JSON, response);\n}\nfunction assertContentTypes(response, ...types) {\n if (!types.includes(getContentType(response))) {\n throw notJson(response, ...types);\n }\n}\nfunction assertContentType(response, contentType) {\n if (getContentType(response) !== contentType) {\n throw notJson(response, contentType);\n }\n}\nfunction randomBytes() {\n return b64u(crypto.getRandomValues(new Uint8Array(32)));\n}\nexport function generateRandomCodeVerifier() {\n return randomBytes();\n}\nexport function generateRandomState() {\n return randomBytes();\n}\nexport function generateRandomNonce() {\n return randomBytes();\n}\nexport async function calculatePKCECodeChallenge(codeVerifier) {\n assertString(codeVerifier, 'codeVerifier');\n return b64u(await crypto.subtle.digest('SHA-256', buf(codeVerifier)));\n}\nfunction getKeyAndKid(input) {\n if (input instanceof CryptoKey) {\n return { key: input };\n }\n if (!(input?.key instanceof CryptoKey)) {\n return {};\n }\n if (input.kid !== undefined) {\n assertString(input.kid, '\"kid\"');\n }\n return {\n key: input.key,\n kid: input.kid,\n };\n}\nfunction psAlg(key) {\n switch (key.algorithm.hash.name) {\n case 'SHA-256':\n return 'PS256';\n case 'SHA-384':\n return 'PS384';\n case 'SHA-512':\n return 'PS512';\n default:\n throw new UnsupportedOperationError('unsupported RsaHashedKeyAlgorithm hash name', {\n cause: key,\n });\n }\n}\nfunction rsAlg(key) {\n switch (key.algorithm.hash.name) {\n case 'SHA-256':\n return 'RS256';\n case 'SHA-384':\n return 'RS384';\n case 'SHA-512':\n return 'RS512';\n default:\n throw new UnsupportedOperationError('unsupported RsaHashedKeyAlgorithm hash name', {\n cause: key,\n });\n }\n}\nfunction esAlg(key) {\n switch (key.algorithm.namedCurve) {\n case 'P-256':\n return 'ES256';\n case 'P-384':\n return 'ES384';\n case 'P-521':\n return 'ES512';\n default:\n throw new UnsupportedOperationError('unsupported EcKeyAlgorithm namedCurve', { cause: key });\n }\n}\nfunction keyToJws(key) {\n switch (key.algorithm.name) {\n case 'RSA-PSS':\n return psAlg(key);\n case 'RSASSA-PKCS1-v1_5':\n return rsAlg(key);\n case 'ECDSA':\n return esAlg(key);\n case 'Ed25519':\n case 'ML-DSA-44':\n case 'ML-DSA-65':\n case 'ML-DSA-87':\n return key.algorithm.name;\n case 'EdDSA':\n return 'Ed25519';\n default:\n throw new UnsupportedOperationError('unsupported CryptoKey algorithm name', { cause: key });\n }\n}\nfunction getClockSkew(client) {\n const skew = client?.[clockSkew];\n return typeof skew === 'number' && Number.isFinite(skew) ? skew : 0;\n}\nfunction getClockTolerance(client) {\n const tolerance = client?.[clockTolerance];\n return typeof tolerance === 'number' && Number.isFinite(tolerance) && Math.sign(tolerance) !== -1\n ? tolerance\n : 30;\n}\nfunction epochTime() {\n return Math.floor(Date.now() / 1000);\n}\nfunction assertAs(as) {\n if (typeof as !== 'object' || as === null) {\n throw CodedTypeError('\"as\" must be an object', ERR_INVALID_ARG_TYPE);\n }\n assertString(as.issuer, '\"as.issuer\"');\n}\nfunction assertClient(client) {\n if (typeof client !== 'object' || client === null) {\n throw CodedTypeError('\"client\" must be an object', ERR_INVALID_ARG_TYPE);\n }\n assertString(client.client_id, '\"client.client_id\"');\n}\nfunction formUrlEncode(token) {\n return encodeURIComponent(token).replace(/(?:[-_.!~*'()]|%20)/g, (substring) => {\n switch (substring) {\n case '-':\n case '_':\n case '.':\n case '!':\n case '~':\n case '*':\n case \"'\":\n case '(':\n case ')':\n return `%${substring.charCodeAt(0).toString(16).toUpperCase()}`;\n case '%20':\n return '+';\n default:\n throw new Error();\n }\n });\n}\nexport function ClientSecretPost(clientSecret) {\n assertString(clientSecret, '\"clientSecret\"');\n return (_as, client, body, _headers) => {\n body.set('client_id', client.client_id);\n body.set('client_secret', clientSecret);\n };\n}\nexport function ClientSecretBasic(clientSecret) {\n assertString(clientSecret, '\"clientSecret\"');\n return (_as, client, _body, headers) => {\n const username = formUrlEncode(client.client_id);\n const password = formUrlEncode(clientSecret);\n const credentials = btoa(`${username}:${password}`);\n headers.set('authorization', `Basic ${credentials}`);\n };\n}\nfunction clientAssertionPayload(as, client) {\n const now = epochTime() + getClockSkew(client);\n return {\n jti: randomBytes(),\n aud: as.issuer,\n exp: now + 60,\n iat: now,\n nbf: now,\n iss: client.client_id,\n sub: client.client_id,\n };\n}\nexport function PrivateKeyJwt(clientPrivateKey, options) {\n const { key, kid } = getKeyAndKid(clientPrivateKey);\n assertPrivateKey(key, '\"clientPrivateKey.key\"');\n return async (as, client, body, _headers) => {\n const header = { alg: keyToJws(key), kid };\n const payload = clientAssertionPayload(as, client);\n options?.[modifyAssertion]?.(header, payload);\n body.set('client_id', client.client_id);\n body.set('client_assertion_type', 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer');\n body.set('client_assertion', await signJwt(header, payload, key));\n };\n}\nexport function ClientSecretJwt(clientSecret, options) {\n assertString(clientSecret, '\"clientSecret\"');\n const modify = options?.[modifyAssertion];\n let key;\n return async (as, client, body, _headers) => {\n key ||= await crypto.subtle.importKey('raw', buf(clientSecret), { hash: 'SHA-256', name: 'HMAC' }, false, ['sign']);\n const header = { alg: 'HS256' };\n const payload = clientAssertionPayload(as, client);\n modify?.(header, payload);\n const data = `${b64u(buf(JSON.stringify(header)))}.${b64u(buf(JSON.stringify(payload)))}`;\n const hmac = await crypto.subtle.sign(key.algorithm, key, buf(data));\n body.set('client_id', client.client_id);\n body.set('client_assertion_type', 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer');\n body.set('client_assertion', `${data}.${b64u(new Uint8Array(hmac))}`);\n };\n}\nexport function None() {\n return (_as, client, body, _headers) => {\n body.set('client_id', client.client_id);\n };\n}\nexport function TlsClientAuth() {\n return None();\n}\nasync function signJwt(header, payload, key) {\n if (!key.usages.includes('sign')) {\n throw CodedTypeError('CryptoKey instances used for signing assertions must include \"sign\" in their \"usages\"', ERR_INVALID_ARG_VALUE);\n }\n const input = `${b64u(buf(JSON.stringify(header)))}.${b64u(buf(JSON.stringify(payload)))}`;\n const signature = b64u(await crypto.subtle.sign(keyToSubtle(key), key, buf(input)));\n return `${input}.${signature}`;\n}\nexport async function issueRequestObject(as, client, parameters, privateKey, options) {\n assertAs(as);\n assertClient(client);\n parameters = new URLSearchParams(parameters);\n const { key, kid } = getKeyAndKid(privateKey);\n assertPrivateKey(key, '\"privateKey.key\"');\n parameters.set('client_id', client.client_id);\n const now = epochTime() + getClockSkew(client);\n const claims = {\n ...Object.fromEntries(parameters.entries()),\n jti: randomBytes(),\n aud: as.issuer,\n exp: now + 60,\n iat: now,\n nbf: now,\n iss: client.client_id,\n };\n let resource;\n if (parameters.has('resource') &&\n (resource = parameters.getAll('resource')) &&\n resource.length > 1) {\n claims.resource = resource;\n }\n {\n let value = parameters.get('max_age');\n if (value !== null) {\n claims.max_age = parseInt(value, 10);\n assertNumber(claims.max_age, true, '\"max_age\" parameter');\n }\n }\n {\n let value = parameters.get('claims');\n if (value !== null) {\n try {\n claims.claims = JSON.parse(value);\n }\n catch (cause) {\n throw OPE('failed to parse the \"claims\" parameter as JSON', PARSE_ERROR, cause);\n }\n if (!isJsonObject(claims.claims)) {\n throw CodedTypeError('\"claims\" parameter must be a JSON with a top level object', ERR_INVALID_ARG_VALUE);\n }\n }\n }\n {\n let value = parameters.get('authorization_details');\n if (value !== null) {\n try {\n claims.authorization_details = JSON.parse(value);\n }\n catch (cause) {\n throw OPE('failed to parse the \"authorization_details\" parameter as JSON', PARSE_ERROR, cause);\n }\n if (!Array.isArray(claims.authorization_details)) {\n throw CodedTypeError('\"authorization_details\" parameter must be a JSON with a top level array', ERR_INVALID_ARG_VALUE);\n }\n }\n }\n const header = {\n alg: keyToJws(key),\n typ: 'oauth-authz-req+jwt',\n kid,\n };\n options?.[modifyAssertion]?.(header, claims);\n return signJwt(header, claims, key);\n}\nlet jwkCache;\nasync function getSetPublicJwkCache(key, alg) {\n const { kty, e, n, x, y, crv, pub } = await crypto.subtle.exportKey('jwk', key);\n const jwk = { kty, e, n, x, y, crv, pub };\n if (kty === 'AKP')\n jwk.alg = alg;\n jwkCache.set(key, jwk);\n return jwk;\n}\nasync function publicJwk(key, alg) {\n jwkCache ||= new WeakMap();\n return jwkCache.get(key) || getSetPublicJwkCache(key, alg);\n}\nconst URLParse = URL.parse\n ?\n (url, base) => URL.parse(url, base)\n : (url, base) => {\n try {\n return new URL(url, base);\n }\n catch {\n return null;\n }\n };\nexport function checkProtocol(url, enforceHttps) {\n if (enforceHttps && url.protocol !== 'https:') {\n throw OPE('only requests to HTTPS are allowed', HTTP_REQUEST_FORBIDDEN, url);\n }\n if (url.protocol !== 'https:' && url.protocol !== 'http:') {\n throw OPE('only HTTP and HTTPS requests are allowed', REQUEST_PROTOCOL_FORBIDDEN, url);\n }\n}\nfunction validateEndpoint(value, endpoint, useMtlsAlias, enforceHttps) {\n let url;\n if (typeof value !== 'string' || !(url = URLParse(value))) {\n throw OPE(`authorization server metadata does not contain a valid ${useMtlsAlias ? `\"as.mtls_endpoint_aliases.${endpoint}\"` : `\"as.${endpoint}\"`}`, value === undefined ? MISSING_SERVER_METADATA : INVALID_SERVER_METADATA, { attribute: useMtlsAlias ? `mtls_endpoint_aliases.${endpoint}` : endpoint });\n }\n checkProtocol(url, enforceHttps);\n return url;\n}\nexport function resolveEndpoint(as, endpoint, useMtlsAlias, enforceHttps) {\n if (useMtlsAlias && as.mtls_endpoint_aliases && endpoint in as.mtls_endpoint_aliases) {\n return validateEndpoint(as.mtls_endpoint_aliases[endpoint], endpoint, useMtlsAlias, enforceHttps);\n }\n return validateEndpoint(as[endpoint], endpoint, useMtlsAlias, enforceHttps);\n}\nexport async function pushedAuthorizationRequest(as, client, clientAuthentication, parameters, options) {\n assertAs(as);\n assertClient(client);\n const url = resolveEndpoint(as, 'pushed_authorization_request_endpoint', client.use_mtls_endpoint_aliases, options?.[allowInsecureRequests] !== true);\n const body = new URLSearchParams(parameters);\n body.set('client_id', client.client_id);\n const headers = prepareHeaders(options?.headers);\n headers.set('accept', 'application/json');\n if (options?.DPoP !== undefined) {\n assertDPoP(options.DPoP);\n await options.DPoP.addProof(url, headers, 'POST');\n }\n const response = await authenticatedRequest(as, client, clientAuthentication, url, body, headers, options);\n options?.DPoP?.cacheNonce(response, url);\n return response;\n}\nclass DPoPHandler {\n #header;\n #privateKey;\n #publicKey;\n #clockSkew;\n #modifyAssertion;\n #map;\n #jkt;\n constructor(client, keyPair, options) {\n assertPrivateKey(keyPair?.privateKey, '\"DPoP.privateKey\"');\n assertPublicKey(keyPair?.publicKey, '\"DPoP.publicKey\"');\n if (!keyPair.publicKey.extractable) {\n throw CodedTypeError('\"DPoP.publicKey.extractable\" must be true', ERR_INVALID_ARG_VALUE);\n }\n this.#modifyAssertion = options?.[modifyAssertion];\n this.#clockSkew = getClockSkew(client);\n this.#privateKey = keyPair.privateKey;\n this.#publicKey = keyPair.publicKey;\n branded.add(this);\n }\n #get(key) {\n this.#map ||= new Map();\n let item = this.#map.get(key);\n if (item) {\n this.#map.delete(key);\n this.#map.set(key, item);\n }\n return item;\n }\n #set(key, val) {\n this.#map ||= new Map();\n this.#map.delete(key);\n if (this.#map.size === 100) {\n this.#map.delete(this.#map.keys().next().value);\n }\n this.#map.set(key, val);\n }\n async calculateThumbprint() {\n if (!this.#jkt) {\n const jwk = await crypto.subtle.exportKey('jwk', this.#publicKey);\n this.#jkt ||= await calculateJwkThumbprint(jwk);\n }\n return this.#jkt;\n }\n async addProof(url, headers, htm, accessToken) {\n const alg = keyToJws(this.#privateKey);\n this.#header ||= {\n alg,\n typ: 'dpop+jwt',\n jwk: await publicJwk(this.#publicKey, alg),\n };\n const nonce = this.#get(url.origin);\n const now = epochTime() + this.#clockSkew;\n const payload = {\n iat: now,\n jti: randomBytes(),\n htm,\n nonce,\n htu: `${url.origin}${url.pathname}`,\n ath: accessToken\n ? b64u(await crypto.subtle.digest('SHA-256', buf(accessToken)))\n : undefined,\n };\n this.#modifyAssertion?.(this.#header, payload);\n headers.set('dpop', await signJwt(this.#header, payload, this.#privateKey));\n }\n cacheNonce(response, url) {\n try {\n const nonce = response.headers.get('dpop-nonce');\n if (nonce) {\n this.#set(url.origin, nonce);\n }\n }\n catch { }\n }\n}\nexport function isDPoPNonceError(err) {\n if (err instanceof WWWAuthenticateChallengeError) {\n const { 0: challenge, length } = err.cause;\n return (length === 1 && challenge.scheme === 'dpop' && challenge.parameters.error === 'use_dpop_nonce');\n }\n if (err instanceof ResponseBodyError) {\n return err.error === 'use_dpop_nonce';\n }\n return false;\n}\nexport function DPoP(client, keyPair, options) {\n return new DPoPHandler(client, keyPair, options);\n}\nexport class ResponseBodyError extends Error {\n cause;\n code;\n error;\n status;\n error_description;\n response;\n constructor(message, options) {\n super(message, options);\n this.name = this.constructor.name;\n this.code = RESPONSE_BODY_ERROR;\n this.cause = options.cause;\n this.error = options.cause.error;\n this.status = options.response.status;\n this.error_description = options.cause.error_description;\n Object.defineProperty(this, 'response', { enumerable: false, value: options.response });\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nexport class AuthorizationResponseError extends Error {\n cause;\n code;\n error;\n error_description;\n constructor(message, options) {\n super(message, options);\n this.name = this.constructor.name;\n this.code = AUTHORIZATION_RESPONSE_ERROR;\n this.cause = options.cause;\n this.error = options.cause.get('error');\n this.error_description = options.cause.get('error_description') ?? undefined;\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nexport class WWWAuthenticateChallengeError extends Error {\n cause;\n code;\n response;\n status;\n constructor(message, options) {\n super(message, options);\n this.name = this.constructor.name;\n this.code = WWW_AUTHENTICATE_CHALLENGE;\n this.cause = options.cause;\n this.status = options.response.status;\n this.response = options.response;\n Object.defineProperty(this, 'response', { enumerable: false });\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nconst tokenMatch = \"[a-zA-Z0-9!#$%&\\\\'\\\\*\\\\+\\\\-\\\\.\\\\^_`\\\\|~]+\";\nconst token68Match = '[a-zA-Z0-9\\\\-\\\\._\\\\~\\\\+\\\\/]+={0,2}';\nconst quotedMatch = '\"((?:[^\"\\\\\\\\]|\\\\\\\\[\\\\s\\\\S])*)\"';\nconst quotedParamMatcher = '(' + tokenMatch + ')\\\\s*=\\\\s*' + quotedMatch;\nconst paramMatcher = '(' + tokenMatch + ')\\\\s*=\\\\s*(' + tokenMatch + ')';\nconst schemeRE = new RegExp('^[,\\\\s]*(' + tokenMatch + ')');\nconst quotedParamRE = new RegExp('^[,\\\\s]*' + quotedParamMatcher + '[,\\\\s]*(.*)');\nconst unquotedParamRE = new RegExp('^[,\\\\s]*' + paramMatcher + '[,\\\\s]*(.*)');\nconst token68ParamRE = new RegExp('^(' + token68Match + ')(?:$|[,\\\\s])(.*)');\nfunction parseWwwAuthenticateChallenges(response) {\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n const header = response.headers.get('www-authenticate');\n if (header === null) {\n return undefined;\n }\n const challenges = [];\n let rest = header;\n while (rest) {\n let match = rest.match(schemeRE);\n const scheme = match?.['1'].toLowerCase();\n if (!scheme) {\n return undefined;\n }\n const afterScheme = rest.substring(match[0].length);\n if (afterScheme && !afterScheme.match(/^[\\s,]/)) {\n return undefined;\n }\n const spaceMatch = afterScheme.match(/^\\s+(.*)$/);\n const hasParameters = !!spaceMatch;\n rest = spaceMatch ? spaceMatch[1] : undefined;\n const parameters = {};\n let token68;\n if (hasParameters) {\n while (rest) {\n let key;\n let value;\n if ((match = rest.match(quotedParamRE))) {\n ;\n [, key, value, rest] = match;\n if (value.includes('\\\\')) {\n try {\n value = JSON.parse(`\"${value}\"`);\n }\n catch { }\n }\n parameters[key.toLowerCase()] = value;\n continue;\n }\n if ((match = rest.match(unquotedParamRE))) {\n ;\n [, key, value, rest] = match;\n parameters[key.toLowerCase()] = value;\n continue;\n }\n if ((match = rest.match(token68ParamRE))) {\n if (Object.keys(parameters).length) {\n break;\n }\n ;\n [, token68, rest] = match;\n break;\n }\n return undefined;\n }\n }\n else {\n rest = afterScheme || undefined;\n }\n const challenge = { scheme, parameters };\n if (token68) {\n challenge.token68 = token68;\n }\n challenges.push(challenge);\n }\n if (!challenges.length) {\n return undefined;\n }\n return challenges;\n}\nexport async function processPushedAuthorizationResponse(as, client, response) {\n assertAs(as);\n assertClient(client);\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n await checkOAuthBodyError(response, 201, 'Pushed Authorization Request Endpoint');\n assertReadableResponse(response);\n const json = await getResponseJsonBody(response);\n assertString(json.request_uri, '\"response\" body \"request_uri\" property', INVALID_RESPONSE, {\n body: json,\n });\n let expiresIn = typeof json.expires_in !== 'number' ? parseFloat(json.expires_in) : json.expires_in;\n assertNumber(expiresIn, true, '\"response\" body \"expires_in\" property', INVALID_RESPONSE, {\n body: json,\n });\n json.expires_in = expiresIn;\n return json;\n}\nasync function parseOAuthResponseErrorBody(response) {\n if (response.status > 399 && response.status < 500) {\n assertReadableResponse(response);\n assertApplicationJson(response);\n try {\n const json = await response.clone().json();\n if (isJsonObject(json) && typeof json.error === 'string' && json.error.length) {\n return json;\n }\n }\n catch { }\n }\n return undefined;\n}\nasync function checkOAuthBodyError(response, expected, label) {\n if (response.status !== expected) {\n checkAuthenticationChallenges(response);\n let err;\n if ((err = await parseOAuthResponseErrorBody(response))) {\n await response.body?.cancel();\n throw new ResponseBodyError('server responded with an error in the response body', {\n cause: err,\n response,\n });\n }\n throw OPE(`\"response\" is not a conform ${label} response (unexpected HTTP status code)`, RESPONSE_IS_NOT_CONFORM, response);\n }\n}\nfunction assertDPoP(option) {\n if (!branded.has(option)) {\n throw CodedTypeError('\"options.DPoP\" is not a valid DPoPHandle', ERR_INVALID_ARG_VALUE);\n }\n}\nasync function resourceRequest(accessToken, method, url, headers, body, options) {\n assertString(accessToken, '\"accessToken\"');\n if (!(url instanceof URL)) {\n throw CodedTypeError('\"url\" must be an instance of URL', ERR_INVALID_ARG_TYPE);\n }\n checkProtocol(url, options?.[allowInsecureRequests] !== true);\n headers = prepareHeaders(headers);\n if (options?.DPoP) {\n assertDPoP(options.DPoP);\n await options.DPoP.addProof(url, headers, method.toUpperCase(), accessToken);\n }\n headers.set('authorization', `${headers.has('dpop') ? 'DPoP' : 'Bearer'} ${accessToken}`);\n const response = await (options?.[customFetch] || fetch)(url.href, {\n body,\n headers: Object.fromEntries(headers.entries()),\n method,\n redirect: 'manual',\n signal: signal(url, options?.signal),\n });\n options?.DPoP?.cacheNonce(response, url);\n return response;\n}\nexport async function protectedResourceRequest(accessToken, method, url, headers, body, options) {\n const response = await resourceRequest(accessToken, method, url, headers, body, options);\n checkAuthenticationChallenges(response);\n return response;\n}\nexport async function userInfoRequest(as, client, accessToken, options) {\n assertAs(as);\n assertClient(client);\n const url = resolveEndpoint(as, 'userinfo_endpoint', client.use_mtls_endpoint_aliases, options?.[allowInsecureRequests] !== true);\n const headers = prepareHeaders(options?.headers);\n if (client.userinfo_signed_response_alg) {\n headers.set('accept', 'application/jwt');\n }\n else {\n headers.set('accept', 'application/json');\n headers.append('accept', 'application/jwt');\n }\n return resourceRequest(accessToken, 'GET', url, headers, null, {\n ...options,\n [clockSkew]: getClockSkew(client),\n });\n}\nlet jwksMap;\nfunction setJwksCache(as, jwks, uat, cache) {\n jwksMap ||= new WeakMap();\n jwksMap.set(as, {\n jwks,\n uat,\n get age() {\n return epochTime() - this.uat;\n },\n });\n if (cache) {\n Object.assign(cache, { jwks: structuredClone(jwks), uat });\n }\n}\nfunction isFreshJwksCache(input) {\n if (typeof input !== 'object' || input === null) {\n return false;\n }\n if (!('uat' in input) || typeof input.uat !== 'number' || epochTime() - input.uat >= 300) {\n return false;\n }\n if (!('jwks' in input) ||\n !isJsonObject(input.jwks) ||\n !Array.isArray(input.jwks.keys) ||\n !Array.prototype.every.call(input.jwks.keys, isJsonObject)) {\n return false;\n }\n return true;\n}\nfunction clearJwksCache(as, cache) {\n jwksMap?.delete(as);\n delete cache?.jwks;\n delete cache?.uat;\n}\nasync function getPublicSigKeyFromIssuerJwksUri(as, options, header) {\n const { alg, kid } = header;\n checkSupportedJwsAlg(header);\n if (!jwksMap?.has(as) && isFreshJwksCache(options?.[jwksCache])) {\n setJwksCache(as, options?.[jwksCache].jwks, options?.[jwksCache].uat);\n }\n let jwks;\n let age;\n if (jwksMap?.has(as)) {\n ;\n ({ jwks, age } = jwksMap.get(as));\n if (age >= 300) {\n clearJwksCache(as, options?.[jwksCache]);\n return getPublicSigKeyFromIssuerJwksUri(as, options, header);\n }\n }\n else {\n jwks = await jwksRequest(as, options).then(processJwksResponse);\n age = 0;\n setJwksCache(as, jwks, epochTime(), options?.[jwksCache]);\n }\n let kty;\n switch (alg.slice(0, 2)) {\n case 'RS':\n case 'PS':\n kty = 'RSA';\n break;\n case 'ES':\n kty = 'EC';\n break;\n case 'Ed':\n kty = 'OKP';\n break;\n case 'ML':\n kty = 'AKP';\n break;\n default:\n throw new UnsupportedOperationError('unsupported JWS algorithm', { cause: { alg } });\n }\n const candidates = jwks.keys.filter((jwk) => {\n if (jwk.kty !== kty) {\n return false;\n }\n if (kid !== undefined && kid !== jwk.kid) {\n return false;\n }\n if (jwk.alg !== undefined && alg !== jwk.alg) {\n return false;\n }\n if (jwk.use !== undefined && jwk.use !== 'sig') {\n return false;\n }\n if (jwk.key_ops?.includes('verify') === false) {\n return false;\n }\n switch (true) {\n case alg === 'ES256' && jwk.crv !== 'P-256':\n case alg === 'ES384' && jwk.crv !== 'P-384':\n case alg === 'ES512' && jwk.crv !== 'P-521':\n case alg === 'Ed25519' && jwk.crv !== 'Ed25519':\n case alg === 'EdDSA' && jwk.crv !== 'Ed25519':\n return false;\n }\n return true;\n });\n const { 0: jwk, length } = candidates;\n if (!length) {\n if (age >= 60) {\n clearJwksCache(as, options?.[jwksCache]);\n return getPublicSigKeyFromIssuerJwksUri(as, options, header);\n }\n throw OPE('error when selecting a JWT verification key, no applicable keys found', KEY_SELECTION, { header, candidates, jwks_uri: new URL(as.jwks_uri) });\n }\n if (length !== 1) {\n throw OPE('error when selecting a JWT verification key, multiple applicable keys found, a \"kid\" JWT Header Parameter is required', KEY_SELECTION, { header, candidates, jwks_uri: new URL(as.jwks_uri) });\n }\n return importJwk(alg, jwk);\n}\nexport const skipSubjectCheck = Symbol();\nexport function getContentType(input) {\n return input.headers.get('content-type')?.split(';')[0];\n}\nexport async function processUserInfoResponse(as, client, expectedSubject, response, options) {\n assertAs(as);\n assertClient(client);\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n checkAuthenticationChallenges(response);\n if (response.status !== 200) {\n throw OPE('\"response\" is not a conform UserInfo Endpoint response (unexpected HTTP status code)', RESPONSE_IS_NOT_CONFORM, response);\n }\n assertReadableResponse(response);\n let json;\n if (getContentType(response) === 'application/jwt') {\n const { claims, jwt } = await validateJwt(await response.text(), checkSigningAlgorithm.bind(undefined, client.userinfo_signed_response_alg, as.userinfo_signing_alg_values_supported, undefined), getClockSkew(client), getClockTolerance(client), options?.[jweDecrypt])\n .then(validateOptionalAudience.bind(undefined, client.client_id))\n .then(validateOptionalIssuer.bind(undefined, as));\n jwtRefs.set(response, jwt);\n json = claims;\n }\n else {\n if (client.userinfo_signed_response_alg) {\n throw OPE('JWT UserInfo Response expected', JWT_USERINFO_EXPECTED, response);\n }\n json = await getResponseJsonBody(response);\n }\n assertString(json.sub, '\"response\" body \"sub\" property', INVALID_RESPONSE, { body: json });\n switch (expectedSubject) {\n case skipSubjectCheck:\n break;\n default:\n assertString(expectedSubject, '\"expectedSubject\"');\n if (json.sub !== expectedSubject) {\n throw OPE('unexpected \"response\" body \"sub\" property value', JSON_ATTRIBUTE_COMPARISON, {\n expected: expectedSubject,\n body: json,\n attribute: 'sub',\n });\n }\n }\n return json;\n}\nasync function authenticatedRequest(as, client, clientAuthentication, url, body, headers, options) {\n await clientAuthentication(as, client, body, headers);\n headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8');\n return (options?.[customFetch] || fetch)(url.href, {\n body,\n headers: Object.fromEntries(headers.entries()),\n method: 'POST',\n redirect: 'manual',\n signal: signal(url, options?.signal),\n });\n}\nasync function tokenEndpointRequest(as, client, clientAuthentication, grantType, parameters, options) {\n const url = resolveEndpoint(as, 'token_endpoint', client.use_mtls_endpoint_aliases, options?.[allowInsecureRequests] !== true);\n parameters.set('grant_type', grantType);\n const headers = prepareHeaders(options?.headers);\n headers.set('accept', 'application/json');\n if (options?.DPoP !== undefined) {\n assertDPoP(options.DPoP);\n await options.DPoP.addProof(url, headers, 'POST');\n }\n const response = await authenticatedRequest(as, client, clientAuthentication, url, parameters, headers, options);\n options?.DPoP?.cacheNonce(response, url);\n return response;\n}\nexport async function refreshTokenGrantRequest(as, client, clientAuthentication, refreshToken, options) {\n assertAs(as);\n assertClient(client);\n assertString(refreshToken, '\"refreshToken\"');\n const parameters = new URLSearchParams(options?.additionalParameters);\n parameters.set('refresh_token', refreshToken);\n return tokenEndpointRequest(as, client, clientAuthentication, 'refresh_token', parameters, options);\n}\nconst idTokenClaims = new WeakMap();\nconst jwtRefs = new WeakMap();\nexport function getValidatedIdTokenClaims(ref) {\n if (!ref.id_token) {\n return undefined;\n }\n const claims = idTokenClaims.get(ref);\n if (!claims) {\n throw CodedTypeError('\"ref\" was already garbage collected or did not resolve from the proper sources', ERR_INVALID_ARG_VALUE);\n }\n return claims;\n}\nexport async function validateApplicationLevelSignature(as, ref, options) {\n assertAs(as);\n if (!jwtRefs.has(ref)) {\n throw CodedTypeError('\"ref\" does not contain a processed JWT Response to verify the signature of', ERR_INVALID_ARG_VALUE);\n }\n const { 0: protectedHeader, 1: payload, 2: encodedSignature } = jwtRefs.get(ref).split('.');\n const header = JSON.parse(buf(b64u(protectedHeader)));\n if (header.alg.startsWith('HS')) {\n throw new UnsupportedOperationError('unsupported JWS algorithm', { cause: { alg: header.alg } });\n }\n let key;\n key = await getPublicSigKeyFromIssuerJwksUri(as, options, header);\n await validateJwsSignature(protectedHeader, payload, key, b64u(encodedSignature));\n}\nasync function processGenericAccessTokenResponse(as, client, response, additionalRequiredIdTokenClaims, decryptFn, recognizedTokenTypes) {\n assertAs(as);\n assertClient(client);\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n await checkOAuthBodyError(response, 200, 'Token Endpoint');\n assertReadableResponse(response);\n const json = await getResponseJsonBody(response);\n assertString(json.access_token, '\"response\" body \"access_token\" property', INVALID_RESPONSE, {\n body: json,\n });\n assertString(json.token_type, '\"response\" body \"token_type\" property', INVALID_RESPONSE, {\n body: json,\n });\n json.token_type = json.token_type.toLowerCase();\n if (json.expires_in !== undefined) {\n let expiresIn = typeof json.expires_in !== 'number' ? parseFloat(json.expires_in) : json.expires_in;\n assertNumber(expiresIn, true, '\"response\" body \"expires_in\" property', INVALID_RESPONSE, {\n body: json,\n });\n json.expires_in = expiresIn;\n }\n if (json.refresh_token !== undefined) {\n assertString(json.refresh_token, '\"response\" body \"refresh_token\" property', INVALID_RESPONSE, {\n body: json,\n });\n }\n if (json.scope !== undefined && typeof json.scope !== 'string') {\n throw OPE('\"response\" body \"scope\" property must be a string', INVALID_RESPONSE, { body: json });\n }\n if (json.id_token !== undefined) {\n assertString(json.id_token, '\"response\" body \"id_token\" property', INVALID_RESPONSE, {\n body: json,\n });\n const requiredClaims = ['aud', 'exp', 'iat', 'iss', 'sub'];\n if (client.require_auth_time === true) {\n requiredClaims.push('auth_time');\n }\n if (client.default_max_age !== undefined) {\n assertNumber(client.default_max_age, true, '\"client.default_max_age\"');\n requiredClaims.push('auth_time');\n }\n if (additionalRequiredIdTokenClaims?.length) {\n requiredClaims.push(...additionalRequiredIdTokenClaims);\n }\n const { claims, jwt } = await validateJwt(json.id_token, checkSigningAlgorithm.bind(undefined, client.id_token_signed_response_alg, as.id_token_signing_alg_values_supported, 'RS256'), getClockSkew(client), getClockTolerance(client), decryptFn)\n .then(validatePresence.bind(undefined, requiredClaims))\n .then(validateIssuer.bind(undefined, as))\n .then(validateAudience.bind(undefined, client.client_id));\n if (Array.isArray(claims.aud) && claims.aud.length !== 1) {\n if (claims.azp === undefined) {\n throw OPE('ID Token \"aud\" (audience) claim includes additional untrusted audiences', JWT_CLAIM_COMPARISON, { claims, claim: 'aud' });\n }\n if (claims.azp !== client.client_id) {\n throw OPE('unexpected ID Token \"azp\" (authorized party) claim value', JWT_CLAIM_COMPARISON, { expected: client.client_id, claims, claim: 'azp' });\n }\n }\n if (claims.auth_time !== undefined) {\n assertNumber(claims.auth_time, true, 'ID Token \"auth_time\" (authentication time)', INVALID_RESPONSE, { claims });\n }\n jwtRefs.set(response, jwt);\n idTokenClaims.set(json, claims);\n }\n if (recognizedTokenTypes?.[json.token_type] !== undefined) {\n recognizedTokenTypes[json.token_type](response, json);\n }\n else if (json.token_type !== 'dpop' && json.token_type !== 'bearer') {\n throw new UnsupportedOperationError('unsupported `token_type` value', { cause: { body: json } });\n }\n return json;\n}\nfunction checkAuthenticationChallenges(response) {\n let challenges;\n if ((challenges = parseWwwAuthenticateChallenges(response))) {\n throw new WWWAuthenticateChallengeError('server responded with a challenge in the WWW-Authenticate HTTP Header', { cause: challenges, response });\n }\n}\nexport async function processRefreshTokenResponse(as, client, response, options) {\n return processGenericAccessTokenResponse(as, client, response, undefined, options?.[jweDecrypt], options?.recognizedTokenTypes);\n}\nfunction validateOptionalAudience(expected, result) {\n if (result.claims.aud !== undefined) {\n return validateAudience(expected, result);\n }\n return result;\n}\nfunction validateAudience(expected, result) {\n if (Array.isArray(result.claims.aud)) {\n if (!result.claims.aud.includes(expected)) {\n throw OPE('unexpected JWT \"aud\" (audience) claim value', JWT_CLAIM_COMPARISON, {\n expected,\n claims: result.claims,\n claim: 'aud',\n });\n }\n }\n else if (result.claims.aud !== expected) {\n throw OPE('unexpected JWT \"aud\" (audience) claim value', JWT_CLAIM_COMPARISON, {\n expected,\n claims: result.claims,\n claim: 'aud',\n });\n }\n return result;\n}\nfunction validateOptionalIssuer(as, result) {\n if (result.claims.iss !== undefined) {\n return validateIssuer(as, result);\n }\n return result;\n}\nfunction validateIssuer(as, result) {\n const expected = as[_expectedIssuer]?.(result) ?? as.issuer;\n if (result.claims.iss !== expected) {\n throw OPE('unexpected JWT \"iss\" (issuer) claim value', JWT_CLAIM_COMPARISON, {\n expected,\n claims: result.claims,\n claim: 'iss',\n });\n }\n return result;\n}\nconst branded = new WeakSet();\nfunction brand(searchParams) {\n branded.add(searchParams);\n return searchParams;\n}\nexport const nopkce = Symbol();\nexport async function authorizationCodeGrantRequest(as, client, clientAuthentication, callbackParameters, redirectUri, codeVerifier, options) {\n assertAs(as);\n assertClient(client);\n if (!branded.has(callbackParameters)) {\n throw CodedTypeError('\"callbackParameters\" must be an instance of URLSearchParams obtained from \"validateAuthResponse()\", or \"validateJwtAuthResponse()', ERR_INVALID_ARG_VALUE);\n }\n assertString(redirectUri, '\"redirectUri\"');\n const code = getURLSearchParameter(callbackParameters, 'code');\n if (!code) {\n throw OPE('no authorization code in \"callbackParameters\"', INVALID_RESPONSE);\n }\n const parameters = new URLSearchParams(options?.additionalParameters);\n parameters.set('redirect_uri', redirectUri);\n parameters.set('code', code);\n if (codeVerifier !== nopkce) {\n assertString(codeVerifier, '\"codeVerifier\"');\n parameters.set('code_verifier', codeVerifier);\n }\n return tokenEndpointRequest(as, client, clientAuthentication, 'authorization_code', parameters, options);\n}\nconst jwtClaimNames = {\n aud: 'audience',\n c_hash: 'code hash',\n client_id: 'client id',\n exp: 'expiration time',\n iat: 'issued at',\n iss: 'issuer',\n jti: 'jwt id',\n nonce: 'nonce',\n s_hash: 'state hash',\n sub: 'subject',\n ath: 'access token hash',\n htm: 'http method',\n htu: 'http uri',\n cnf: 'confirmation',\n auth_time: 'authentication time',\n};\nfunction validatePresence(required, result) {\n for (const claim of required) {\n if (result.claims[claim] === undefined) {\n throw OPE(`JWT \"${claim}\" (${jwtClaimNames[claim]}) claim missing`, INVALID_RESPONSE, {\n claims: result.claims,\n });\n }\n }\n return result;\n}\nexport const expectNoNonce = Symbol();\nexport const skipAuthTimeCheck = Symbol();\nexport async function processAuthorizationCodeResponse(as, client, response, options) {\n if (typeof options?.expectedNonce === 'string' ||\n typeof options?.maxAge === 'number' ||\n options?.requireIdToken) {\n return processAuthorizationCodeOpenIDResponse(as, client, response, options.expectedNonce, options.maxAge, options[jweDecrypt], options.recognizedTokenTypes);\n }\n return processAuthorizationCodeOAuth2Response(as, client, response, options?.[jweDecrypt], options?.recognizedTokenTypes);\n}\nasync function processAuthorizationCodeOpenIDResponse(as, client, response, expectedNonce, maxAge, decryptFn, recognizedTokenTypes) {\n const additionalRequiredClaims = [];\n switch (expectedNonce) {\n case undefined:\n expectedNonce = expectNoNonce;\n break;\n case expectNoNonce:\n break;\n default:\n assertString(expectedNonce, '\"expectedNonce\" argument');\n additionalRequiredClaims.push('nonce');\n }\n maxAge ??= client.default_max_age;\n switch (maxAge) {\n case undefined:\n maxAge = skipAuthTimeCheck;\n break;\n case skipAuthTimeCheck:\n break;\n default:\n assertNumber(maxAge, true, '\"maxAge\" argument');\n additionalRequiredClaims.push('auth_time');\n }\n const result = await processGenericAccessTokenResponse(as, client, response, additionalRequiredClaims, decryptFn, recognizedTokenTypes);\n assertString(result.id_token, '\"response\" body \"id_token\" property', INVALID_RESPONSE, {\n body: result,\n });\n const claims = getValidatedIdTokenClaims(result);\n if (maxAge !== skipAuthTimeCheck) {\n const now = epochTime() + getClockSkew(client);\n const tolerance = getClockTolerance(client);\n if (claims.auth_time + maxAge < now - tolerance) {\n throw OPE('too much time has elapsed since the last End-User authentication', JWT_TIMESTAMP_CHECK, { claims, now, tolerance, claim: 'auth_time' });\n }\n }\n if (expectedNonce === expectNoNonce) {\n if (claims.nonce !== undefined) {\n throw OPE('unexpected ID Token \"nonce\" claim value', JWT_CLAIM_COMPARISON, {\n expected: undefined,\n claims,\n claim: 'nonce',\n });\n }\n }\n else if (claims.nonce !== expectedNonce) {\n throw OPE('unexpected ID Token \"nonce\" claim value', JWT_CLAIM_COMPARISON, {\n expected: expectedNonce,\n claims,\n claim: 'nonce',\n });\n }\n return result;\n}\nasync function processAuthorizationCodeOAuth2Response(as, client, response, decryptFn, recognizedTokenTypes) {\n const result = await processGenericAccessTokenResponse(as, client, response, undefined, decryptFn, recognizedTokenTypes);\n const claims = getValidatedIdTokenClaims(result);\n if (claims) {\n if (client.default_max_age !== undefined) {\n assertNumber(client.default_max_age, true, '\"client.default_max_age\"');\n const now = epochTime() + getClockSkew(client);\n const tolerance = getClockTolerance(client);\n if (claims.auth_time + client.default_max_age < now - tolerance) {\n throw OPE('too much time has elapsed since the last End-User authentication', JWT_TIMESTAMP_CHECK, { claims, now, tolerance, claim: 'auth_time' });\n }\n }\n if (claims.nonce !== undefined) {\n throw OPE('unexpected ID Token \"nonce\" claim value', JWT_CLAIM_COMPARISON, {\n expected: undefined,\n claims,\n claim: 'nonce',\n });\n }\n }\n return result;\n}\nexport const WWW_AUTHENTICATE_CHALLENGE = 'OAUTH_WWW_AUTHENTICATE_CHALLENGE';\nexport const RESPONSE_BODY_ERROR = 'OAUTH_RESPONSE_BODY_ERROR';\nexport const UNSUPPORTED_OPERATION = 'OAUTH_UNSUPPORTED_OPERATION';\nexport const AUTHORIZATION_RESPONSE_ERROR = 'OAUTH_AUTHORIZATION_RESPONSE_ERROR';\nexport const JWT_USERINFO_EXPECTED = 'OAUTH_JWT_USERINFO_EXPECTED';\nexport const PARSE_ERROR = 'OAUTH_PARSE_ERROR';\nexport const INVALID_RESPONSE = 'OAUTH_INVALID_RESPONSE';\nexport const INVALID_REQUEST = 'OAUTH_INVALID_REQUEST';\nexport const RESPONSE_IS_NOT_JSON = 'OAUTH_RESPONSE_IS_NOT_JSON';\nexport const RESPONSE_IS_NOT_CONFORM = 'OAUTH_RESPONSE_IS_NOT_CONFORM';\nexport const HTTP_REQUEST_FORBIDDEN = 'OAUTH_HTTP_REQUEST_FORBIDDEN';\nexport const REQUEST_PROTOCOL_FORBIDDEN = 'OAUTH_REQUEST_PROTOCOL_FORBIDDEN';\nexport const JWT_TIMESTAMP_CHECK = 'OAUTH_JWT_TIMESTAMP_CHECK_FAILED';\nexport const JWT_CLAIM_COMPARISON = 'OAUTH_JWT_CLAIM_COMPARISON_FAILED';\nexport const JSON_ATTRIBUTE_COMPARISON = 'OAUTH_JSON_ATTRIBUTE_COMPARISON_FAILED';\nexport const KEY_SELECTION = 'OAUTH_KEY_SELECTION_FAILED';\nexport const MISSING_SERVER_METADATA = 'OAUTH_MISSING_SERVER_METADATA';\nexport const INVALID_SERVER_METADATA = 'OAUTH_INVALID_SERVER_METADATA';\nfunction checkJwtType(expected, result) {\n if (typeof result.header.typ !== 'string' || normalizeTyp(result.header.typ) !== expected) {\n throw OPE('unexpected JWT \"typ\" header parameter value', INVALID_RESPONSE, {\n header: result.header,\n });\n }\n return result;\n}\nexport async function clientCredentialsGrantRequest(as, client, clientAuthentication, parameters, options) {\n assertAs(as);\n assertClient(client);\n return tokenEndpointRequest(as, client, clientAuthentication, 'client_credentials', new URLSearchParams(parameters), options);\n}\nexport async function genericTokenEndpointRequest(as, client, clientAuthentication, grantType, parameters, options) {\n assertAs(as);\n assertClient(client);\n assertString(grantType, '\"grantType\"');\n return tokenEndpointRequest(as, client, clientAuthentication, grantType, new URLSearchParams(parameters), options);\n}\nexport async function processGenericTokenEndpointResponse(as, client, response, options) {\n return processGenericAccessTokenResponse(as, client, response, undefined, options?.[jweDecrypt], options?.recognizedTokenTypes);\n}\nexport async function processClientCredentialsResponse(as, client, response, options) {\n return processGenericAccessTokenResponse(as, client, response, undefined, options?.[jweDecrypt], options?.recognizedTokenTypes);\n}\nexport async function revocationRequest(as, client, clientAuthentication, token, options) {\n assertAs(as);\n assertClient(client);\n assertString(token, '\"token\"');\n const url = resolveEndpoint(as, 'revocation_endpoint', client.use_mtls_endpoint_aliases, options?.[allowInsecureRequests] !== true);\n const body = new URLSearchParams(options?.additionalParameters);\n body.set('token', token);\n const headers = prepareHeaders(options?.headers);\n headers.delete('accept');\n return authenticatedRequest(as, client, clientAuthentication, url, body, headers, options);\n}\nexport async function processRevocationResponse(response) {\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n await checkOAuthBodyError(response, 200, 'Revocation Endpoint');\n return undefined;\n}\nfunction assertReadableResponse(response) {\n if (response.bodyUsed) {\n throw CodedTypeError('\"response\" body has been used already', ERR_INVALID_ARG_VALUE);\n }\n}\nexport async function introspectionRequest(as, client, clientAuthentication, token, options) {\n assertAs(as);\n assertClient(client);\n assertString(token, '\"token\"');\n const url = resolveEndpoint(as, 'introspection_endpoint', client.use_mtls_endpoint_aliases, options?.[allowInsecureRequests] !== true);\n const body = new URLSearchParams(options?.additionalParameters);\n body.set('token', token);\n const headers = prepareHeaders(options?.headers);\n if (options?.requestJwtResponse ?? client.introspection_signed_response_alg) {\n headers.set('accept', 'application/token-introspection+jwt');\n }\n else {\n headers.set('accept', 'application/json');\n }\n return authenticatedRequest(as, client, clientAuthentication, url, body, headers, options);\n}\nexport async function processIntrospectionResponse(as, client, response, options) {\n assertAs(as);\n assertClient(client);\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n await checkOAuthBodyError(response, 200, 'Introspection Endpoint');\n let json;\n if (getContentType(response) === 'application/token-introspection+jwt') {\n assertReadableResponse(response);\n const { claims, jwt } = await validateJwt(await response.text(), checkSigningAlgorithm.bind(undefined, client.introspection_signed_response_alg, as.introspection_signing_alg_values_supported, 'RS256'), getClockSkew(client), getClockTolerance(client), options?.[jweDecrypt])\n .then(checkJwtType.bind(undefined, 'token-introspection+jwt'))\n .then(validatePresence.bind(undefined, ['aud', 'iat', 'iss']))\n .then(validateIssuer.bind(undefined, as))\n .then(validateAudience.bind(undefined, client.client_id));\n jwtRefs.set(response, jwt);\n if (!isJsonObject(claims.token_introspection)) {\n throw OPE('JWT \"token_introspection\" claim must be a JSON object', INVALID_RESPONSE, {\n claims,\n });\n }\n json = claims.token_introspection;\n }\n else {\n assertReadableResponse(response);\n json = await getResponseJsonBody(response);\n }\n if (typeof json.active !== 'boolean') {\n throw OPE('\"response\" body \"active\" property must be a boolean', INVALID_RESPONSE, {\n body: json,\n });\n }\n return json;\n}\nasync function jwksRequest(as, options) {\n assertAs(as);\n const url = resolveEndpoint(as, 'jwks_uri', false, options?.[allowInsecureRequests] !== true);\n const headers = prepareHeaders(options?.headers);\n headers.set('accept', 'application/json');\n headers.append('accept', 'application/jwk-set+json');\n return (options?.[customFetch] || fetch)(url.href, {\n body: undefined,\n headers: Object.fromEntries(headers.entries()),\n method: 'GET',\n redirect: 'manual',\n signal: signal(url, options?.signal),\n });\n}\nasync function processJwksResponse(response) {\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n if (response.status !== 200) {\n throw OPE('\"response\" is not a conform JSON Web Key Set response (unexpected HTTP status code)', RESPONSE_IS_NOT_CONFORM, response);\n }\n assertReadableResponse(response);\n const json = await getResponseJsonBody(response, (response) => assertContentTypes(response, 'application/json', 'application/jwk-set+json'));\n if (!Array.isArray(json.keys)) {\n throw OPE('\"response\" body \"keys\" property must be an array', INVALID_RESPONSE, { body: json });\n }\n if (!Array.prototype.every.call(json.keys, isJsonObject)) {\n throw OPE('\"response\" body \"keys\" property members must be JWK formatted objects', INVALID_RESPONSE, { body: json });\n }\n return json;\n}\nfunction supported(alg) {\n switch (alg) {\n case 'PS256':\n case 'ES256':\n case 'RS256':\n case 'PS384':\n case 'ES384':\n case 'RS384':\n case 'PS512':\n case 'ES512':\n case 'RS512':\n case 'Ed25519':\n case 'EdDSA':\n case 'ML-DSA-44':\n case 'ML-DSA-65':\n case 'ML-DSA-87':\n return true;\n default:\n return false;\n }\n}\nfunction checkSupportedJwsAlg(header) {\n if (!supported(header.alg)) {\n throw new UnsupportedOperationError('unsupported JWS \"alg\" identifier', {\n cause: { alg: header.alg },\n });\n }\n}\nfunction checkRsaKeyAlgorithm(key) {\n const { algorithm } = key;\n if (typeof algorithm.modulusLength !== 'number' || algorithm.modulusLength < 2048) {\n throw new UnsupportedOperationError(`unsupported ${algorithm.name} modulusLength`, {\n cause: key,\n });\n }\n}\nfunction ecdsaHashName(key) {\n const { algorithm } = key;\n switch (algorithm.namedCurve) {\n case 'P-256':\n return 'SHA-256';\n case 'P-384':\n return 'SHA-384';\n case 'P-521':\n return 'SHA-512';\n default:\n throw new UnsupportedOperationError('unsupported ECDSA namedCurve', { cause: key });\n }\n}\nfunction keyToSubtle(key) {\n switch (key.algorithm.name) {\n case 'ECDSA':\n return {\n name: key.algorithm.name,\n hash: ecdsaHashName(key),\n };\n case 'RSA-PSS': {\n checkRsaKeyAlgorithm(key);\n switch (key.algorithm.hash.name) {\n case 'SHA-256':\n case 'SHA-384':\n case 'SHA-512':\n return {\n name: key.algorithm.name,\n saltLength: parseInt(key.algorithm.hash.name.slice(-3), 10) >> 3,\n };\n default:\n throw new UnsupportedOperationError('unsupported RSA-PSS hash name', { cause: key });\n }\n }\n case 'RSASSA-PKCS1-v1_5':\n checkRsaKeyAlgorithm(key);\n return key.algorithm.name;\n case 'ML-DSA-44':\n case 'ML-DSA-65':\n case 'ML-DSA-87':\n case 'Ed25519':\n return key.algorithm.name;\n }\n throw new UnsupportedOperationError('unsupported CryptoKey algorithm name', { cause: key });\n}\nasync function validateJwsSignature(protectedHeader, payload, key, signature) {\n const data = buf(`${protectedHeader}.${payload}`);\n const algorithm = keyToSubtle(key);\n const verified = await crypto.subtle.verify(algorithm, key, signature, data);\n if (!verified) {\n throw OPE('JWT signature verification failed', INVALID_RESPONSE, {\n key,\n data,\n signature,\n algorithm,\n });\n }\n}\nasync function validateJwt(jws, checkAlg, clockSkew, clockTolerance, decryptJwt) {\n let { 0: protectedHeader, 1: payload, length } = jws.split('.');\n if (length === 5) {\n if (decryptJwt !== undefined) {\n jws = await decryptJwt(jws);\n ({ 0: protectedHeader, 1: payload, length } = jws.split('.'));\n }\n else {\n throw new UnsupportedOperationError('JWE decryption is not configured', { cause: jws });\n }\n }\n if (length !== 3) {\n throw OPE('Invalid JWT', INVALID_RESPONSE, jws);\n }\n let header;\n try {\n header = JSON.parse(buf(b64u(protectedHeader)));\n }\n catch (cause) {\n throw OPE('failed to parse JWT Header body as base64url encoded JSON', PARSE_ERROR, cause);\n }\n if (!isJsonObject(header)) {\n throw OPE('JWT Header must be a top level object', INVALID_RESPONSE, jws);\n }\n checkAlg(header);\n if (header.crit !== undefined) {\n throw new UnsupportedOperationError('no JWT \"crit\" header parameter extensions are supported', {\n cause: { header },\n });\n }\n let claims;\n try {\n claims = JSON.parse(buf(b64u(payload)));\n }\n catch (cause) {\n throw OPE('failed to parse JWT Payload body as base64url encoded JSON', PARSE_ERROR, cause);\n }\n if (!isJsonObject(claims)) {\n throw OPE('JWT Payload must be a top level object', INVALID_RESPONSE, jws);\n }\n const now = epochTime() + clockSkew;\n if (claims.exp !== undefined) {\n if (typeof claims.exp !== 'number') {\n throw OPE('unexpected JWT \"exp\" (expiration time) claim type', INVALID_RESPONSE, { claims });\n }\n if (claims.exp <= now - clockTolerance) {\n throw OPE('unexpected JWT \"exp\" (expiration time) claim value, expiration is past current timestamp', JWT_TIMESTAMP_CHECK, { claims, now, tolerance: clockTolerance, claim: 'exp' });\n }\n }\n if (claims.iat !== undefined) {\n if (typeof claims.iat !== 'number') {\n throw OPE('unexpected JWT \"iat\" (issued at) claim type', INVALID_RESPONSE, { claims });\n }\n }\n if (claims.iss !== undefined) {\n if (typeof claims.iss !== 'string') {\n throw OPE('unexpected JWT \"iss\" (issuer) claim type', INVALID_RESPONSE, { claims });\n }\n }\n if (claims.nbf !== undefined) {\n if (typeof claims.nbf !== 'number') {\n throw OPE('unexpected JWT \"nbf\" (not before) claim type', INVALID_RESPONSE, { claims });\n }\n if (claims.nbf > now + clockTolerance) {\n throw OPE('unexpected JWT \"nbf\" (not before) claim value', JWT_TIMESTAMP_CHECK, {\n claims,\n now,\n tolerance: clockTolerance,\n claim: 'nbf',\n });\n }\n }\n if (claims.aud !== undefined) {\n if (typeof claims.aud !== 'string' && !Array.isArray(claims.aud)) {\n throw OPE('unexpected JWT \"aud\" (audience) claim type', INVALID_RESPONSE, { claims });\n }\n }\n return { header, claims, jwt: jws };\n}\nexport async function validateJwtAuthResponse(as, client, parameters, expectedState, options) {\n assertAs(as);\n assertClient(client);\n if (parameters instanceof URL) {\n parameters = parameters.searchParams;\n }\n if (!(parameters instanceof URLSearchParams)) {\n throw CodedTypeError('\"parameters\" must be an instance of URLSearchParams, or URL', ERR_INVALID_ARG_TYPE);\n }\n const response = getURLSearchParameter(parameters, 'response');\n if (!response) {\n throw OPE('\"parameters\" does not contain a JARM response', INVALID_RESPONSE);\n }\n const { claims, header, jwt } = await validateJwt(response, checkSigningAlgorithm.bind(undefined, client.authorization_signed_response_alg, as.authorization_signing_alg_values_supported, 'RS256'), getClockSkew(client), getClockTolerance(client), options?.[jweDecrypt])\n .then(validatePresence.bind(undefined, ['aud', 'exp', 'iss']))\n .then(validateIssuer.bind(undefined, as))\n .then(validateAudience.bind(undefined, client.client_id));\n const { 0: protectedHeader, 1: payload, 2: encodedSignature } = jwt.split('.');\n const signature = b64u(encodedSignature);\n const key = await getPublicSigKeyFromIssuerJwksUri(as, options, header);\n await validateJwsSignature(protectedHeader, payload, key, signature);\n const result = new URLSearchParams();\n for (const [key, value] of Object.entries(claims)) {\n if (typeof value === 'string' && key !== 'aud') {\n result.set(key, value);\n }\n }\n return validateAuthResponse(as, client, result, expectedState);\n}\nasync function idTokenHash(data, header, claimName) {\n let algorithm;\n switch (header.alg) {\n case 'RS256':\n case 'PS256':\n case 'ES256':\n algorithm = 'SHA-256';\n break;\n case 'RS384':\n case 'PS384':\n case 'ES384':\n algorithm = 'SHA-384';\n break;\n case 'RS512':\n case 'PS512':\n case 'ES512':\n case 'Ed25519':\n case 'EdDSA':\n algorithm = 'SHA-512';\n break;\n case 'ML-DSA-44':\n case 'ML-DSA-65':\n case 'ML-DSA-87':\n algorithm = { name: 'cSHAKE256', length: 512 };\n break;\n default:\n throw new UnsupportedOperationError(`unsupported JWS algorithm for ${claimName} calculation`, { cause: { alg: header.alg } });\n }\n const digest = await crypto.subtle.digest(algorithm, buf(data));\n return b64u(digest.slice(0, digest.byteLength / 2));\n}\nasync function idTokenHashMatches(data, actual, header, claimName) {\n const expected = await idTokenHash(data, header, claimName);\n return actual === expected;\n}\nexport async function validateDetachedSignatureResponse(as, client, parameters, expectedNonce, expectedState, maxAge, options) {\n return validateHybridResponse(as, client, parameters, expectedNonce, expectedState, maxAge, options, true);\n}\nexport async function validateCodeIdTokenResponse(as, client, parameters, expectedNonce, expectedState, maxAge, options) {\n return validateHybridResponse(as, client, parameters, expectedNonce, expectedState, maxAge, options, false);\n}\nasync function consumeStream(request) {\n if (request.bodyUsed) {\n throw CodedTypeError('form_post Request instances must contain a readable body', ERR_INVALID_ARG_VALUE, { cause: request });\n }\n return request.text();\n}\nexport async function formPostResponse(request) {\n if (request.method !== 'POST') {\n throw CodedTypeError('form_post responses are expected to use the POST method', ERR_INVALID_ARG_VALUE, { cause: request });\n }\n if (getContentType(request) !== 'application/x-www-form-urlencoded') {\n throw CodedTypeError('form_post responses are expected to use the application/x-www-form-urlencoded content-type', ERR_INVALID_ARG_VALUE, { cause: request });\n }\n return consumeStream(request);\n}\nasync function validateHybridResponse(as, client, parameters, expectedNonce, expectedState, maxAge, options, fapi) {\n assertAs(as);\n assertClient(client);\n if (parameters instanceof URL) {\n if (!parameters.hash.length) {\n throw CodedTypeError('\"parameters\" as an instance of URL must contain a hash (fragment) with the Authorization Response parameters', ERR_INVALID_ARG_VALUE);\n }\n parameters = new URLSearchParams(parameters.hash.slice(1));\n }\n else if (looseInstanceOf(parameters, Request)) {\n parameters = new URLSearchParams(await formPostResponse(parameters));\n }\n else if (parameters instanceof URLSearchParams) {\n parameters = new URLSearchParams(parameters);\n }\n else {\n throw CodedTypeError('\"parameters\" must be an instance of URLSearchParams, URL, or Response', ERR_INVALID_ARG_TYPE);\n }\n const id_token = getURLSearchParameter(parameters, 'id_token');\n parameters.delete('id_token');\n switch (expectedState) {\n case undefined:\n case expectNoState:\n break;\n default:\n assertString(expectedState, '\"expectedState\" argument');\n }\n const result = validateAuthResponse({\n ...as,\n authorization_response_iss_parameter_supported: false,\n }, client, parameters, expectedState);\n if (!id_token) {\n throw OPE('\"parameters\" does not contain an ID Token', INVALID_RESPONSE);\n }\n const code = getURLSearchParameter(parameters, 'code');\n if (!code) {\n throw OPE('\"parameters\" does not contain an Authorization Code', INVALID_RESPONSE);\n }\n const requiredClaims = [\n 'aud',\n 'exp',\n 'iat',\n 'iss',\n 'sub',\n 'nonce',\n 'c_hash',\n ];\n const state = parameters.get('state');\n if (fapi && (typeof expectedState === 'string' || state !== null)) {\n requiredClaims.push('s_hash');\n }\n if (maxAge !== undefined) {\n assertNumber(maxAge, true, '\"maxAge\" argument');\n }\n else if (client.default_max_age !== undefined) {\n assertNumber(client.default_max_age, true, '\"client.default_max_age\"');\n }\n maxAge ??= client.default_max_age ?? skipAuthTimeCheck;\n if (client.require_auth_time || maxAge !== skipAuthTimeCheck) {\n requiredClaims.push('auth_time');\n }\n const { claims, header, jwt } = await validateJwt(id_token, checkSigningAlgorithm.bind(undefined, client.id_token_signed_response_alg, as.id_token_signing_alg_values_supported, 'RS256'), getClockSkew(client), getClockTolerance(client), options?.[jweDecrypt])\n .then(validatePresence.bind(undefined, requiredClaims))\n .then(validateIssuer.bind(undefined, as))\n .then(validateAudience.bind(undefined, client.client_id));\n const clockSkew = getClockSkew(client);\n const now = epochTime() + clockSkew;\n if (claims.iat < now - 3600) {\n throw OPE('unexpected JWT \"iat\" (issued at) claim value, it is too far in the past', JWT_TIMESTAMP_CHECK, { now, claims, claim: 'iat' });\n }\n assertString(claims.c_hash, 'ID Token \"c_hash\" (code hash) claim value', INVALID_RESPONSE, {\n claims,\n });\n if (claims.auth_time !== undefined) {\n assertNumber(claims.auth_time, true, 'ID Token \"auth_time\" (authentication time)', INVALID_RESPONSE, { claims });\n }\n if (maxAge !== skipAuthTimeCheck) {\n const now = epochTime() + getClockSkew(client);\n const tolerance = getClockTolerance(client);\n if (claims.auth_time + maxAge < now - tolerance) {\n throw OPE('too much time has elapsed since the last End-User authentication', JWT_TIMESTAMP_CHECK, { claims, now, tolerance, claim: 'auth_time' });\n }\n }\n assertString(expectedNonce, '\"expectedNonce\" argument');\n if (claims.nonce !== expectedNonce) {\n throw OPE('unexpected ID Token \"nonce\" claim value', JWT_CLAIM_COMPARISON, {\n expected: expectedNonce,\n claims,\n claim: 'nonce',\n });\n }\n if (Array.isArray(claims.aud) && claims.aud.length !== 1) {\n if (claims.azp === undefined) {\n throw OPE('ID Token \"aud\" (audience) claim includes additional untrusted audiences', JWT_CLAIM_COMPARISON, { claims, claim: 'aud' });\n }\n if (claims.azp !== client.client_id) {\n throw OPE('unexpected ID Token \"azp\" (authorized party) claim value', JWT_CLAIM_COMPARISON, {\n expected: client.client_id,\n claims,\n claim: 'azp',\n });\n }\n }\n const { 0: protectedHeader, 1: payload, 2: encodedSignature } = jwt.split('.');\n const signature = b64u(encodedSignature);\n const key = await getPublicSigKeyFromIssuerJwksUri(as, options, header);\n await validateJwsSignature(protectedHeader, payload, key, signature);\n if ((await idTokenHashMatches(code, claims.c_hash, header, 'c_hash')) !== true) {\n throw OPE('invalid ID Token \"c_hash\" (code hash) claim value', JWT_CLAIM_COMPARISON, {\n code,\n alg: header.alg,\n claim: 'c_hash',\n claims,\n });\n }\n if ((fapi && state !== null) || claims.s_hash !== undefined) {\n assertString(claims.s_hash, 'ID Token \"s_hash\" (state hash) claim value', INVALID_RESPONSE, {\n claims,\n });\n assertString(state, '\"state\" response parameter', INVALID_RESPONSE, { parameters });\n if ((await idTokenHashMatches(state, claims.s_hash, header, 's_hash')) !== true) {\n throw OPE('invalid ID Token \"s_hash\" (state hash) claim value', JWT_CLAIM_COMPARISON, {\n state,\n alg: header.alg,\n claim: 's_hash',\n claims,\n });\n }\n }\n return result;\n}\nfunction checkSigningAlgorithm(client, issuer, fallback, header) {\n if (client !== undefined) {\n if (typeof client === 'string' ? header.alg !== client : !client.includes(header.alg)) {\n throw OPE('unexpected JWT \"alg\" header parameter', INVALID_RESPONSE, {\n header,\n expected: client,\n reason: 'client configuration',\n });\n }\n return;\n }\n if (Array.isArray(issuer)) {\n if (!issuer.includes(header.alg)) {\n throw OPE('unexpected JWT \"alg\" header parameter', INVALID_RESPONSE, {\n header,\n expected: issuer,\n reason: 'authorization server metadata',\n });\n }\n return;\n }\n if (fallback !== undefined) {\n if (typeof fallback === 'string'\n ? header.alg !== fallback\n : typeof fallback === 'function'\n ? !fallback(header.alg)\n : !fallback.includes(header.alg)) {\n throw OPE('unexpected JWT \"alg\" header parameter', INVALID_RESPONSE, {\n header,\n expected: fallback,\n reason: 'default value',\n });\n }\n return;\n }\n throw OPE('missing client or server configuration to verify used JWT \"alg\" header parameter', undefined, { client, issuer, fallback });\n}\nfunction getURLSearchParameter(parameters, name) {\n const { 0: value, length } = parameters.getAll(name);\n if (length > 1) {\n throw OPE(`\"${name}\" parameter must be provided only once`, INVALID_RESPONSE);\n }\n return value;\n}\nexport const skipStateCheck = Symbol();\nexport const expectNoState = Symbol();\nexport function validateAuthResponse(as, client, parameters, expectedState) {\n assertAs(as);\n assertClient(client);\n if (parameters instanceof URL) {\n parameters = parameters.searchParams;\n }\n if (!(parameters instanceof URLSearchParams)) {\n throw CodedTypeError('\"parameters\" must be an instance of URLSearchParams, or URL', ERR_INVALID_ARG_TYPE);\n }\n if (getURLSearchParameter(parameters, 'response')) {\n throw OPE('\"parameters\" contains a JARM response, use validateJwtAuthResponse() instead of validateAuthResponse()', INVALID_RESPONSE, { parameters });\n }\n const iss = getURLSearchParameter(parameters, 'iss');\n const state = getURLSearchParameter(parameters, 'state');\n if (!iss && as.authorization_response_iss_parameter_supported) {\n throw OPE('response parameter \"iss\" (issuer) missing', INVALID_RESPONSE, { parameters });\n }\n if (iss && iss !== as.issuer) {\n throw OPE('unexpected \"iss\" (issuer) response parameter value', INVALID_RESPONSE, {\n expected: as.issuer,\n parameters,\n });\n }\n switch (expectedState) {\n case undefined:\n case expectNoState:\n if (state !== undefined) {\n throw OPE('unexpected \"state\" response parameter encountered', INVALID_RESPONSE, {\n expected: undefined,\n parameters,\n });\n }\n break;\n case skipStateCheck:\n break;\n default:\n assertString(expectedState, '\"expectedState\" argument');\n if (state !== expectedState) {\n throw OPE(state === undefined\n ? 'response parameter \"state\" missing'\n : 'unexpected \"state\" response parameter value', INVALID_RESPONSE, { expected: expectedState, parameters });\n }\n }\n const error = getURLSearchParameter(parameters, 'error');\n if (error) {\n throw new AuthorizationResponseError('authorization response from the server is an error', {\n cause: parameters,\n });\n }\n const id_token = getURLSearchParameter(parameters, 'id_token');\n const token = getURLSearchParameter(parameters, 'token');\n if (id_token !== undefined || token !== undefined) {\n throw new UnsupportedOperationError('implicit and hybrid flows are not supported');\n }\n return brand(new URLSearchParams(parameters));\n}\nfunction algToSubtle(alg) {\n switch (alg) {\n case 'PS256':\n case 'PS384':\n case 'PS512':\n return { name: 'RSA-PSS', hash: `SHA-${alg.slice(-3)}` };\n case 'RS256':\n case 'RS384':\n case 'RS512':\n return { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${alg.slice(-3)}` };\n case 'ES256':\n case 'ES384':\n return { name: 'ECDSA', namedCurve: `P-${alg.slice(-3)}` };\n case 'ES512':\n return { name: 'ECDSA', namedCurve: 'P-521' };\n case 'EdDSA':\n return 'Ed25519';\n case 'Ed25519':\n case 'ML-DSA-44':\n case 'ML-DSA-65':\n case 'ML-DSA-87':\n return alg;\n default:\n throw new UnsupportedOperationError('unsupported JWS algorithm', { cause: { alg } });\n }\n}\nasync function importJwk(alg, jwk) {\n const { ext, key_ops, use, ...key } = jwk;\n return crypto.subtle.importKey('jwk', key, algToSubtle(alg), true, ['verify']);\n}\nexport async function deviceAuthorizationRequest(as, client, clientAuthentication, parameters, options) {\n assertAs(as);\n assertClient(client);\n const url = resolveEndpoint(as, 'device_authorization_endpoint', client.use_mtls_endpoint_aliases, options?.[allowInsecureRequests] !== true);\n const body = new URLSearchParams(parameters);\n body.set('client_id', client.client_id);\n const headers = prepareHeaders(options?.headers);\n headers.set('accept', 'application/json');\n return authenticatedRequest(as, client, clientAuthentication, url, body, headers, options);\n}\nexport async function processDeviceAuthorizationResponse(as, client, response) {\n assertAs(as);\n assertClient(client);\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n await checkOAuthBodyError(response, 200, 'Device Authorization Endpoint');\n assertReadableResponse(response);\n const json = await getResponseJsonBody(response);\n assertString(json.device_code, '\"response\" body \"device_code\" property', INVALID_RESPONSE, {\n body: json,\n });\n assertString(json.user_code, '\"response\" body \"user_code\" property', INVALID_RESPONSE, {\n body: json,\n });\n assertString(json.verification_uri, '\"response\" body \"verification_uri\" property', INVALID_RESPONSE, { body: json });\n let expiresIn = typeof json.expires_in !== 'number' ? parseFloat(json.expires_in) : json.expires_in;\n assertNumber(expiresIn, true, '\"response\" body \"expires_in\" property', INVALID_RESPONSE, {\n body: json,\n });\n json.expires_in = expiresIn;\n if (json.verification_uri_complete !== undefined) {\n assertString(json.verification_uri_complete, '\"response\" body \"verification_uri_complete\" property', INVALID_RESPONSE, { body: json });\n }\n if (json.interval !== undefined) {\n assertNumber(json.interval, false, '\"response\" body \"interval\" property', INVALID_RESPONSE, {\n body: json,\n });\n }\n return json;\n}\nexport async function deviceCodeGrantRequest(as, client, clientAuthentication, deviceCode, options) {\n assertAs(as);\n assertClient(client);\n assertString(deviceCode, '\"deviceCode\"');\n const parameters = new URLSearchParams(options?.additionalParameters);\n parameters.set('device_code', deviceCode);\n return tokenEndpointRequest(as, client, clientAuthentication, 'urn:ietf:params:oauth:grant-type:device_code', parameters, options);\n}\nexport async function processDeviceCodeResponse(as, client, response, options) {\n return processGenericAccessTokenResponse(as, client, response, undefined, options?.[jweDecrypt], options?.recognizedTokenTypes);\n}\nexport async function generateKeyPair(alg, options) {\n assertString(alg, '\"alg\"');\n const algorithm = algToSubtle(alg);\n if (alg.startsWith('PS') || alg.startsWith('RS')) {\n Object.assign(algorithm, {\n modulusLength: options?.modulusLength ?? 2048,\n publicExponent: new Uint8Array([0x01, 0x00, 0x01]),\n });\n }\n return crypto.subtle.generateKey(algorithm, options?.extractable ?? false, [\n 'sign',\n 'verify',\n ]);\n}\nfunction normalizeHtu(htu) {\n const url = new URL(htu);\n url.search = '';\n url.hash = '';\n return url.href;\n}\nasync function validateDPoP(request, accessToken, accessTokenClaims, options) {\n const headerValue = request.headers.get('dpop');\n if (headerValue === null) {\n throw OPE('operation indicated DPoP use but the request has no DPoP HTTP Header', INVALID_REQUEST, { headers: request.headers });\n }\n if (request.headers.get('authorization')?.toLowerCase().startsWith('dpop ') === false) {\n throw OPE(`operation indicated DPoP use but the request's Authorization HTTP Header scheme is not DPoP`, INVALID_REQUEST, { headers: request.headers });\n }\n if (typeof accessTokenClaims.cnf?.jkt !== 'string') {\n throw OPE('operation indicated DPoP use but the JWT Access Token has no jkt confirmation claim', INVALID_REQUEST, { claims: accessTokenClaims });\n }\n const clockSkew = getClockSkew(options);\n const proof = await validateJwt(headerValue, checkSigningAlgorithm.bind(undefined, options?.signingAlgorithms, undefined, supported), clockSkew, getClockTolerance(options), undefined)\n .then(checkJwtType.bind(undefined, 'dpop+jwt'))\n .then(validatePresence.bind(undefined, ['iat', 'jti', 'ath', 'htm', 'htu']));\n const now = epochTime() + clockSkew;\n const diff = Math.abs(now - proof.claims.iat);\n if (diff > 300) {\n throw OPE('DPoP Proof iat is not recent enough', JWT_TIMESTAMP_CHECK, {\n now,\n claims: proof.claims,\n claim: 'iat',\n });\n }\n if (proof.claims.htm !== request.method) {\n throw OPE('DPoP Proof htm mismatch', JWT_CLAIM_COMPARISON, {\n expected: request.method,\n claims: proof.claims,\n claim: 'htm',\n });\n }\n if (typeof proof.claims.htu !== 'string' ||\n normalizeHtu(proof.claims.htu) !== normalizeHtu(request.url)) {\n throw OPE('DPoP Proof htu mismatch', JWT_CLAIM_COMPARISON, {\n expected: normalizeHtu(request.url),\n claims: proof.claims,\n claim: 'htu',\n });\n }\n {\n const expected = b64u(await crypto.subtle.digest('SHA-256', buf(accessToken)));\n if (proof.claims.ath !== expected) {\n throw OPE('DPoP Proof ath mismatch', JWT_CLAIM_COMPARISON, {\n expected,\n claims: proof.claims,\n claim: 'ath',\n });\n }\n }\n {\n const expected = await calculateJwkThumbprint(proof.header.jwk);\n if (accessTokenClaims.cnf.jkt !== expected) {\n throw OPE('JWT Access Token confirmation mismatch', JWT_CLAIM_COMPARISON, {\n expected,\n claims: accessTokenClaims,\n claim: 'cnf.jkt',\n });\n }\n }\n const { 0: protectedHeader, 1: payload, 2: encodedSignature } = headerValue.split('.');\n const signature = b64u(encodedSignature);\n const { jwk, alg } = proof.header;\n if (!jwk) {\n throw OPE('DPoP Proof is missing the jwk header parameter', INVALID_REQUEST, {\n header: proof.header,\n });\n }\n const key = await importJwk(alg, jwk);\n if (key.type !== 'public') {\n throw OPE('DPoP Proof jwk header parameter must contain a public key', INVALID_REQUEST, {\n header: proof.header,\n });\n }\n await validateJwsSignature(protectedHeader, payload, key, signature);\n}\nexport async function validateJwtAccessToken(as, request, expectedAudience, options) {\n assertAs(as);\n if (!looseInstanceOf(request, Request)) {\n throw CodedTypeError('\"request\" must be an instance of Request', ERR_INVALID_ARG_TYPE);\n }\n assertString(expectedAudience, '\"expectedAudience\"');\n const authorization = request.headers.get('authorization');\n if (authorization === null) {\n throw OPE('\"request\" is missing an Authorization HTTP Header', INVALID_REQUEST, {\n headers: request.headers,\n });\n }\n let { 0: scheme, 1: accessToken, length } = authorization.split(' ');\n scheme = scheme.toLowerCase();\n switch (scheme) {\n case 'dpop':\n case 'bearer':\n break;\n default:\n throw new UnsupportedOperationError('unsupported Authorization HTTP Header scheme', {\n cause: { headers: request.headers },\n });\n }\n if (length !== 2) {\n throw OPE('invalid Authorization HTTP Header format', INVALID_REQUEST, {\n headers: request.headers,\n });\n }\n const requiredClaims = [\n 'iss',\n 'exp',\n 'aud',\n 'sub',\n 'iat',\n 'jti',\n 'client_id',\n ];\n if (options?.requireDPoP || scheme === 'dpop' || request.headers.has('dpop')) {\n requiredClaims.push('cnf');\n }\n const { claims, header } = await validateJwt(accessToken, checkSigningAlgorithm.bind(undefined, options?.signingAlgorithms, undefined, supported), getClockSkew(options), getClockTolerance(options), undefined)\n .then(checkJwtType.bind(undefined, 'at+jwt'))\n .then(validatePresence.bind(undefined, requiredClaims))\n .then(validateIssuer.bind(undefined, as))\n .then(validateAudience.bind(undefined, expectedAudience))\n .catch(reassignRSCode);\n for (const claim of ['client_id', 'jti', 'sub']) {\n if (typeof claims[claim] !== 'string') {\n throw OPE(`unexpected JWT \"${claim}\" claim type`, INVALID_REQUEST, { claims });\n }\n }\n if ('cnf' in claims) {\n if (!isJsonObject(claims.cnf)) {\n throw OPE('unexpected JWT \"cnf\" (confirmation) claim value', INVALID_REQUEST, { claims });\n }\n const { 0: cnf, length } = Object.keys(claims.cnf);\n if (length) {\n if (length !== 1) {\n throw new UnsupportedOperationError('multiple confirmation claims are not supported', {\n cause: { claims },\n });\n }\n if (cnf !== 'jkt') {\n throw new UnsupportedOperationError('unsupported JWT Confirmation method', {\n cause: { claims },\n });\n }\n }\n }\n const { 0: protectedHeader, 1: payload, 2: encodedSignature } = accessToken.split('.');\n const signature = b64u(encodedSignature);\n const key = await getPublicSigKeyFromIssuerJwksUri(as, options, header);\n await validateJwsSignature(protectedHeader, payload, key, signature);\n if (options?.requireDPoP ||\n scheme === 'dpop' ||\n claims.cnf?.jkt !== undefined ||\n request.headers.has('dpop')) {\n await validateDPoP(request, accessToken, claims, options).catch(reassignRSCode);\n }\n return claims;\n}\nfunction reassignRSCode(err) {\n if (err instanceof OperationProcessingError && err?.code === INVALID_REQUEST) {\n err.code = INVALID_RESPONSE;\n }\n throw err;\n}\nexport async function backchannelAuthenticationRequest(as, client, clientAuthentication, parameters, options) {\n assertAs(as);\n assertClient(client);\n const url = resolveEndpoint(as, 'backchannel_authentication_endpoint', client.use_mtls_endpoint_aliases, options?.[allowInsecureRequests] !== true);\n const body = new URLSearchParams(parameters);\n body.set('client_id', client.client_id);\n const headers = prepareHeaders(options?.headers);\n headers.set('accept', 'application/json');\n return authenticatedRequest(as, client, clientAuthentication, url, body, headers, options);\n}\nexport async function processBackchannelAuthenticationResponse(as, client, response) {\n assertAs(as);\n assertClient(client);\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n await checkOAuthBodyError(response, 200, 'Backchannel Authentication Endpoint');\n assertReadableResponse(response);\n const json = await getResponseJsonBody(response);\n assertString(json.auth_req_id, '\"response\" body \"auth_req_id\" property', INVALID_RESPONSE, {\n body: json,\n });\n let expiresIn = typeof json.expires_in !== 'number' ? parseFloat(json.expires_in) : json.expires_in;\n assertNumber(expiresIn, true, '\"response\" body \"expires_in\" property', INVALID_RESPONSE, {\n body: json,\n });\n json.expires_in = expiresIn;\n if (json.interval !== undefined) {\n assertNumber(json.interval, false, '\"response\" body \"interval\" property', INVALID_RESPONSE, {\n body: json,\n });\n }\n return json;\n}\nexport async function backchannelAuthenticationGrantRequest(as, client, clientAuthentication, authReqId, options) {\n assertAs(as);\n assertClient(client);\n assertString(authReqId, '\"authReqId\"');\n const parameters = new URLSearchParams(options?.additionalParameters);\n parameters.set('auth_req_id', authReqId);\n return tokenEndpointRequest(as, client, clientAuthentication, 'urn:openid:params:grant-type:ciba', parameters, options);\n}\nexport async function processBackchannelAuthenticationGrantResponse(as, client, response, options) {\n return processGenericAccessTokenResponse(as, client, response, undefined, options?.[jweDecrypt], options?.recognizedTokenTypes);\n}\nexport async function dynamicClientRegistrationRequest(as, metadata, options) {\n assertAs(as);\n const url = resolveEndpoint(as, 'registration_endpoint', metadata.use_mtls_endpoint_aliases, options?.[allowInsecureRequests] !== true);\n const headers = prepareHeaders(options?.headers);\n headers.set('accept', 'application/json');\n headers.set('content-type', 'application/json');\n const method = 'POST';\n if (options?.DPoP) {\n assertDPoP(options.DPoP);\n await options.DPoP.addProof(url, headers, method, options.initialAccessToken);\n }\n if (options?.initialAccessToken) {\n headers.set('authorization', `${headers.has('dpop') ? 'DPoP' : 'Bearer'} ${options.initialAccessToken}`);\n }\n const response = await (options?.[customFetch] || fetch)(url.href, {\n body: JSON.stringify(metadata),\n headers: Object.fromEntries(headers.entries()),\n method,\n redirect: 'manual',\n signal: signal(url, options?.signal),\n });\n options?.DPoP?.cacheNonce(response, url);\n return response;\n}\nexport async function processDynamicClientRegistrationResponse(response) {\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n await checkOAuthBodyError(response, 201, 'Dynamic Client Registration Endpoint');\n assertReadableResponse(response);\n const json = await getResponseJsonBody(response);\n assertString(json.client_id, '\"response\" body \"client_id\" property', INVALID_RESPONSE, {\n body: json,\n });\n if (json.client_secret !== undefined) {\n assertString(json.client_secret, '\"response\" body \"client_secret\" property', INVALID_RESPONSE, {\n body: json,\n });\n }\n if (json.client_secret) {\n assertNumber(json.client_secret_expires_at, true, '\"response\" body \"client_secret_expires_at\" property', INVALID_RESPONSE, {\n body: json,\n });\n }\n return json;\n}\nexport async function resourceDiscoveryRequest(resourceIdentifier, options) {\n return performDiscovery(resourceIdentifier, 'resourceIdentifier', (url) => {\n prependWellKnown(url, '.well-known/oauth-protected-resource', true);\n return url;\n }, options);\n}\nexport async function processResourceDiscoveryResponse(expectedResourceIdentifier, response) {\n const expected = expectedResourceIdentifier;\n if (!(expected instanceof URL) && expected !== _nodiscoverycheck) {\n throw CodedTypeError('\"expectedResourceIdentifier\" must be an instance of URL', ERR_INVALID_ARG_TYPE);\n }\n if (!looseInstanceOf(response, Response)) {\n throw CodedTypeError('\"response\" must be an instance of Response', ERR_INVALID_ARG_TYPE);\n }\n if (response.status !== 200) {\n throw OPE('\"response\" is not a conform Resource Server Metadata response (unexpected HTTP status code)', RESPONSE_IS_NOT_CONFORM, response);\n }\n assertReadableResponse(response);\n const json = await getResponseJsonBody(response);\n assertString(json.resource, '\"response\" body \"resource\" property', INVALID_RESPONSE, {\n body: json,\n });\n if (expected !== _nodiscoverycheck && new URL(json.resource).href !== expected.href) {\n throw OPE('\"response\" body \"resource\" property does not match the expected value', JSON_ATTRIBUTE_COMPARISON, { expected: expected.href, body: json, attribute: 'resource' });\n }\n return json;\n}\nasync function getResponseJsonBody(response, check = assertApplicationJson) {\n let json;\n try {\n json = await response.json();\n }\n catch (cause) {\n check(response);\n throw OPE('failed to parse \"response\" body as JSON', PARSE_ERROR, cause);\n }\n if (!isJsonObject(json)) {\n throw OPE('\"response\" body must be a top level object', INVALID_RESPONSE, { body: json });\n }\n return json;\n}\nexport const _nopkce = nopkce;\nexport const _nodiscoverycheck = Symbol();\nexport const _expectedIssuer = Symbol();\n//# sourceMappingURL=index.js.map","import * as oauth from 'oauth4webapi';\nimport { compactDecrypt } from 'jose/jwe/compact/decrypt';\nimport { JOSEError } from 'jose/errors';\nlet headers;\nlet USER_AGENT;\nif (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {\n const NAME = 'openid-client';\n const VERSION = 'v6.8.1';\n USER_AGENT = `${NAME}/${VERSION}`;\n headers = { 'user-agent': USER_AGENT };\n}\nconst int = (config) => {\n return props.get(config);\n};\nlet props;\nexport { AuthorizationResponseError, ResponseBodyError, WWWAuthenticateChallengeError, } from 'oauth4webapi';\nlet tbi;\nexport function ClientSecretPost(clientSecret) {\n if (clientSecret !== undefined) {\n return oauth.ClientSecretPost(clientSecret);\n }\n tbi ||= new WeakMap();\n return (as, client, body, headers) => {\n let auth;\n if (!(auth = tbi.get(client))) {\n assertString(client.client_secret, '\"metadata.client_secret\"');\n auth = oauth.ClientSecretPost(client.client_secret);\n tbi.set(client, auth);\n }\n return auth(as, client, body, headers);\n };\n}\nfunction assertString(input, it) {\n if (typeof input !== 'string') {\n throw CodedTypeError(`${it} must be a string`, ERR_INVALID_ARG_TYPE);\n }\n if (input.length === 0) {\n throw CodedTypeError(`${it} must not be empty`, ERR_INVALID_ARG_VALUE);\n }\n}\nexport function ClientSecretBasic(clientSecret) {\n if (clientSecret !== undefined) {\n return oauth.ClientSecretBasic(clientSecret);\n }\n tbi ||= new WeakMap();\n return (as, client, body, headers) => {\n let auth;\n if (!(auth = tbi.get(client))) {\n assertString(client.client_secret, '\"metadata.client_secret\"');\n auth = oauth.ClientSecretBasic(client.client_secret);\n tbi.set(client, auth);\n }\n return auth(as, client, body, headers);\n };\n}\nexport function ClientSecretJwt(clientSecret, options) {\n if (clientSecret !== undefined) {\n return oauth.ClientSecretJwt(clientSecret, options);\n }\n tbi ||= new WeakMap();\n return (as, client, body, headers) => {\n let auth;\n if (!(auth = tbi.get(client))) {\n assertString(client.client_secret, '\"metadata.client_secret\"');\n auth = oauth.ClientSecretJwt(client.client_secret, options);\n tbi.set(client, auth);\n }\n return auth(as, client, body, headers);\n };\n}\nexport function None() {\n return oauth.None();\n}\nexport function PrivateKeyJwt(clientPrivateKey, options) {\n return oauth.PrivateKeyJwt(clientPrivateKey, options);\n}\nexport function TlsClientAuth() {\n return oauth.TlsClientAuth();\n}\nexport const skipStateCheck = oauth.skipStateCheck;\nexport const skipSubjectCheck = oauth.skipSubjectCheck;\nexport const customFetch = oauth.customFetch;\nexport const modifyAssertion = oauth.modifyAssertion;\nexport const clockSkew = oauth.clockSkew;\nexport const clockTolerance = oauth.clockTolerance;\nconst ERR_INVALID_ARG_VALUE = 'ERR_INVALID_ARG_VALUE';\nconst ERR_INVALID_ARG_TYPE = 'ERR_INVALID_ARG_TYPE';\nfunction CodedTypeError(message, code, cause) {\n const err = new TypeError(message, { cause });\n Object.assign(err, { code });\n return err;\n}\nexport function calculatePKCECodeChallenge(codeVerifier) {\n return oauth.calculatePKCECodeChallenge(codeVerifier);\n}\nexport function randomPKCECodeVerifier() {\n return oauth.generateRandomCodeVerifier();\n}\nexport function randomNonce() {\n return oauth.generateRandomNonce();\n}\nexport function randomState() {\n return oauth.generateRandomState();\n}\nexport class ClientError extends Error {\n code;\n constructor(message, options) {\n super(message, options);\n this.name = this.constructor.name;\n this.code = options?.code;\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nconst decoder = new TextDecoder();\nfunction e(msg, cause, code) {\n return new ClientError(msg, { cause, code });\n}\nfunction errorHandler(err) {\n if (err instanceof TypeError ||\n err instanceof ClientError ||\n err instanceof oauth.ResponseBodyError ||\n err instanceof oauth.AuthorizationResponseError ||\n err instanceof oauth.WWWAuthenticateChallengeError) {\n throw err;\n }\n if (err instanceof oauth.OperationProcessingError) {\n switch (err.code) {\n case oauth.HTTP_REQUEST_FORBIDDEN:\n throw e('only requests to HTTPS are allowed', err, err.code);\n case oauth.REQUEST_PROTOCOL_FORBIDDEN:\n throw e('only requests to HTTP or HTTPS are allowed', err, err.code);\n case oauth.RESPONSE_IS_NOT_CONFORM:\n throw e('unexpected HTTP response status code', err.cause, err.code);\n case oauth.RESPONSE_IS_NOT_JSON:\n throw e('unexpected response content-type', err.cause, err.code);\n case oauth.PARSE_ERROR:\n throw e('parsing error occured', err, err.code);\n case oauth.INVALID_RESPONSE:\n throw e('invalid response encountered', err, err.code);\n case oauth.JWT_CLAIM_COMPARISON:\n throw e('unexpected JWT claim value encountered', err, err.code);\n case oauth.JSON_ATTRIBUTE_COMPARISON:\n throw e('unexpected JSON attribute value encountered', err, err.code);\n case oauth.JWT_TIMESTAMP_CHECK:\n throw e('JWT timestamp claim value failed validation', err, err.code);\n default:\n throw e(err.message, err, err.code);\n }\n }\n if (err instanceof oauth.UnsupportedOperationError) {\n throw e('unsupported operation', err, err.code);\n }\n if (err instanceof DOMException) {\n switch (err.name) {\n case 'OperationError':\n throw e('runtime operation error', err, oauth.UNSUPPORTED_OPERATION);\n case 'NotSupportedError':\n throw e('runtime unsupported operation', err, oauth.UNSUPPORTED_OPERATION);\n case 'TimeoutError':\n throw e('operation timed out', err, 'OAUTH_TIMEOUT');\n case 'AbortError':\n throw e('operation aborted', err, 'OAUTH_ABORT');\n }\n }\n throw new ClientError('something went wrong', { cause: err });\n}\nexport function randomDPoPKeyPair(alg, options) {\n return oauth\n .generateKeyPair(alg ?? 'ES256', {\n extractable: options?.extractable,\n })\n .catch(errorHandler);\n}\nfunction handleEntraId(server, as, options) {\n if (server.origin === 'https://login.microsoftonline.com' &&\n (!options?.algorithm || options.algorithm === 'oidc')) {\n as[kEntraId] = true;\n return true;\n }\n return false;\n}\nfunction handleB2Clogin(server, options) {\n if (server.hostname.endsWith('.b2clogin.com') &&\n (!options?.algorithm || options.algorithm === 'oidc')) {\n return true;\n }\n return false;\n}\nexport async function dynamicClientRegistration(server, metadata, clientAuthentication, options) {\n let as;\n if (options?.flag === retry) {\n as = options.as;\n }\n else {\n as = await performDiscovery(server, options);\n }\n const clockSkew = metadata[oauth.clockSkew] ?? 0;\n const clockTolerance = metadata[oauth.clockTolerance] ?? 30;\n metadata = structuredClone(metadata);\n const timeout = options?.timeout ?? 30;\n const signal = AbortSignal.timeout(timeout * 1000);\n let registered;\n try {\n registered = await oauth\n .dynamicClientRegistrationRequest(as, metadata, {\n initialAccessToken: options?.initialAccessToken,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n [oauth.customFetch]: options?.[customFetch],\n [oauth.allowInsecureRequests]: options?.execute?.includes(allowInsecureRequests),\n signal,\n })\n .then(oauth.processDynamicClientRegistrationResponse);\n }\n catch (err) {\n if (retryable(err, options)) {\n return dynamicClientRegistration(server, metadata, clientAuthentication, {\n ...options,\n flag: retry,\n as,\n });\n }\n errorHandler(err);\n }\n registered[oauth.clockSkew] = clockSkew;\n registered[oauth.clockTolerance] = clockTolerance;\n const instance = new Configuration(as, registered.client_id, registered, clientAuthentication);\n let internals = int(instance);\n if (options?.[customFetch]) {\n internals.fetch = options[customFetch];\n }\n if (options?.timeout) {\n internals.timeout = options.timeout;\n }\n if (options?.execute) {\n for (const extension of options.execute) {\n extension(instance);\n }\n }\n return instance;\n}\nexport async function discovery(server, clientId, metadata, clientAuthentication, options) {\n const as = await performDiscovery(server, options);\n const instance = new Configuration(as, clientId, metadata, clientAuthentication);\n let internals = int(instance);\n if (options?.[customFetch]) {\n internals.fetch = options[customFetch];\n }\n if (options?.timeout) {\n internals.timeout = options.timeout;\n }\n if (options?.execute) {\n for (const extension of options.execute) {\n extension(instance);\n }\n }\n return instance;\n}\nasync function performDiscovery(server, options) {\n if (!(server instanceof URL)) {\n throw CodedTypeError('\"server\" must be an instance of URL', ERR_INVALID_ARG_TYPE);\n }\n const resolve = !server.href.includes('/.well-known/');\n const timeout = options?.timeout ?? 30;\n const signal = AbortSignal.timeout(timeout * 1000);\n const as = await (resolve\n ? oauth.discoveryRequest(server, {\n algorithm: options?.algorithm,\n [oauth.customFetch]: options?.[customFetch],\n [oauth.allowInsecureRequests]: options?.execute?.includes(allowInsecureRequests),\n signal,\n headers: new Headers(headers),\n })\n : (options?.[customFetch] || fetch)((() => {\n oauth.checkProtocol(server, options?.execute?.includes(allowInsecureRequests) ? false : true);\n return server.href;\n })(), {\n headers: Object.fromEntries(new Headers({ accept: 'application/json', ...headers }).entries()),\n body: undefined,\n method: 'GET',\n redirect: 'manual',\n signal,\n }))\n .then((response) => oauth.processDiscoveryResponse(oauth._nodiscoverycheck, response))\n .catch(errorHandler);\n if (resolve && new URL(as.issuer).href !== server.href) {\n handleEntraId(server, as, options) ||\n handleB2Clogin(server, options) ||\n (() => {\n throw new ClientError('discovered metadata issuer does not match the expected issuer', {\n code: oauth.JSON_ATTRIBUTE_COMPARISON,\n cause: {\n expected: server.href,\n body: as,\n attribute: 'issuer',\n },\n });\n })();\n }\n return as;\n}\nfunction isRsaOaep(input) {\n return input.name === 'RSA-OAEP';\n}\nfunction isEcdh(input) {\n return input.name === 'ECDH';\n}\nconst ecdhEs = 'ECDH-ES';\nconst ecdhEsA128Kw = 'ECDH-ES+A128KW';\nconst ecdhEsA192Kw = 'ECDH-ES+A192KW';\nconst ecdhEsA256Kw = 'ECDH-ES+A256KW';\nfunction checkEcdhAlg(algs, alg, pk) {\n switch (alg) {\n case undefined:\n algs.add(ecdhEs);\n algs.add(ecdhEsA128Kw);\n algs.add(ecdhEsA192Kw);\n algs.add(ecdhEsA256Kw);\n break;\n case ecdhEs:\n case ecdhEsA128Kw:\n case ecdhEsA192Kw:\n case ecdhEsA256Kw:\n algs.add(alg);\n break;\n default:\n throw CodedTypeError('invalid key alg', ERR_INVALID_ARG_VALUE, { pk });\n }\n}\nexport function enableDecryptingResponses(config, contentEncryptionAlgorithms = [\n 'A128GCM',\n 'A192GCM',\n 'A256GCM',\n 'A128CBC-HS256',\n 'A192CBC-HS384',\n 'A256CBC-HS512',\n], ...keys) {\n if (int(config).decrypt !== undefined) {\n throw new TypeError('enableDecryptingResponses can only be called on a given Configuration instance once');\n }\n if (keys.length === 0) {\n throw CodedTypeError('no keys were provided', ERR_INVALID_ARG_VALUE);\n }\n const algs = new Set();\n const normalized = [];\n for (const pk of keys) {\n let key;\n if ('key' in pk) {\n key = { key: pk.key };\n if (typeof pk.alg === 'string')\n key.alg = pk.alg;\n if (typeof pk.kid === 'string')\n key.kid = pk.kid;\n }\n else {\n key = { key: pk };\n }\n if (key.key.type !== 'private') {\n throw CodedTypeError('only private keys must be provided', ERR_INVALID_ARG_VALUE);\n }\n if (isRsaOaep(key.key.algorithm)) {\n switch (key.key.algorithm.hash.name) {\n case 'SHA-1':\n case 'SHA-256':\n case 'SHA-384':\n case 'SHA-512': {\n let alg = 'RSA-OAEP';\n let sha;\n if ((sha = parseInt(key.key.algorithm.hash.name.slice(-3), 10))) {\n alg = `${alg}-${sha}`;\n }\n key.alg ||= alg;\n if (alg !== key.alg)\n throw CodedTypeError('invalid key alg', ERR_INVALID_ARG_VALUE, {\n pk,\n });\n algs.add(key.alg);\n break;\n }\n default:\n throw CodedTypeError('only SHA-512, SHA-384, SHA-256, and SHA-1 RSA-OAEP keys are supported', ERR_INVALID_ARG_VALUE);\n }\n }\n else if (isEcdh(key.key.algorithm)) {\n if (key.key.algorithm.namedCurve !== 'P-256') {\n throw CodedTypeError('Only P-256 ECDH keys are supported', ERR_INVALID_ARG_VALUE);\n }\n checkEcdhAlg(algs, key.alg, pk);\n }\n else if (key.key.algorithm.name === 'X25519') {\n checkEcdhAlg(algs, key.alg, pk);\n }\n else {\n throw CodedTypeError('only RSA-OAEP, ECDH, or X25519 keys are supported', ERR_INVALID_ARG_VALUE);\n }\n normalized.push(key);\n }\n int(config).decrypt = async (jwe) => decrypt(normalized, jwe, contentEncryptionAlgorithms, [...algs]).catch(errorHandler);\n}\nfunction checkCryptoKey(key, alg, epk) {\n if (alg.startsWith('RSA-OAEP')) {\n return true;\n }\n if (alg.startsWith('ECDH-ES')) {\n if (key.algorithm.name !== 'ECDH' && key.algorithm.name !== 'X25519') {\n return false;\n }\n if (key.algorithm.name === 'ECDH') {\n return epk?.crv === key.algorithm.namedCurve;\n }\n if (key.algorithm.name === 'X25519') {\n return epk?.crv === 'X25519';\n }\n }\n return false;\n}\nfunction selectCryptoKeyForDecryption(keys, alg, kid, epk) {\n const { 0: key, length } = keys.filter((key) => {\n if (kid !== key.kid) {\n return false;\n }\n if (key.alg && alg !== key.alg) {\n return false;\n }\n return checkCryptoKey(key.key, alg, epk);\n });\n if (!key) {\n throw e('no applicable decryption key selected', undefined, 'OAUTH_DECRYPTION_FAILED');\n }\n if (length !== 1) {\n throw e('multiple applicable decryption keys selected', undefined, 'OAUTH_DECRYPTION_FAILED');\n }\n return key.key;\n}\nasync function decrypt(keys, jwe, contentEncryptionAlgorithms, keyManagementAlgorithms) {\n return decoder.decode((await compactDecrypt(jwe, (header) => {\n const { kid, alg, epk } = header;\n return selectCryptoKeyForDecryption(keys, alg, kid, epk);\n }, { keyManagementAlgorithms, contentEncryptionAlgorithms }).catch((err) => {\n if (err instanceof JOSEError) {\n throw e('decryption failed', err, 'OAUTH_DECRYPTION_FAILED');\n }\n errorHandler(err);\n })).plaintext);\n}\nfunction getServerHelpers(metadata) {\n return {\n supportsPKCE: {\n __proto__: null,\n value(method = 'S256') {\n return (metadata.code_challenge_methods_supported?.includes(method) === true);\n },\n },\n };\n}\nfunction addServerHelpers(metadata) {\n Object.defineProperties(metadata, getServerHelpers(metadata));\n}\nconst kEntraId = Symbol();\nexport class Configuration {\n constructor(server, clientId, metadata, clientAuthentication) {\n if (typeof clientId !== 'string' || !clientId.length) {\n throw CodedTypeError('\"clientId\" must be a non-empty string', ERR_INVALID_ARG_TYPE);\n }\n if (typeof metadata === 'string') {\n metadata = { client_secret: metadata };\n }\n if (metadata?.client_id !== undefined && clientId !== metadata.client_id) {\n throw CodedTypeError('\"clientId\" and \"metadata.client_id\" must be the same', ERR_INVALID_ARG_VALUE);\n }\n const client = {\n ...structuredClone(metadata),\n client_id: clientId,\n };\n client[oauth.clockSkew] = metadata?.[oauth.clockSkew] ?? 0;\n client[oauth.clockTolerance] = metadata?.[oauth.clockTolerance] ?? 30;\n let auth;\n if (clientAuthentication) {\n auth = clientAuthentication;\n }\n else {\n if (typeof client.client_secret === 'string' &&\n client.client_secret.length) {\n auth = ClientSecretPost(client.client_secret);\n }\n else {\n auth = None();\n }\n }\n let c = Object.freeze(client);\n const clone = structuredClone(server);\n if (kEntraId in server) {\n clone[oauth._expectedIssuer] = ({ claims: { tid } }) => server.issuer.replace('{tenantid}', tid);\n }\n let as = Object.freeze(clone);\n props ||= new WeakMap();\n props.set(this, {\n __proto__: null,\n as,\n c,\n auth,\n tlsOnly: true,\n jwksCache: {},\n });\n }\n serverMetadata() {\n const metadata = structuredClone(int(this).as);\n addServerHelpers(metadata);\n return metadata;\n }\n clientMetadata() {\n const metadata = structuredClone(int(this).c);\n return metadata;\n }\n get timeout() {\n return int(this).timeout;\n }\n set timeout(value) {\n int(this).timeout = value;\n }\n get [customFetch]() {\n return int(this).fetch;\n }\n set [customFetch](value) {\n int(this).fetch = value;\n }\n}\nObject.freeze(Configuration.prototype);\nfunction getHelpers(response) {\n let exp = undefined;\n if (response.expires_in !== undefined) {\n const now = new Date();\n now.setSeconds(now.getSeconds() + response.expires_in);\n exp = now.getTime();\n }\n return {\n expiresIn: {\n __proto__: null,\n value() {\n if (exp) {\n const now = Date.now();\n if (exp > now) {\n return Math.floor((exp - now) / 1000);\n }\n return 0;\n }\n return undefined;\n },\n },\n claims: {\n __proto__: null,\n value() {\n try {\n return oauth.getValidatedIdTokenClaims(this);\n }\n catch {\n return undefined;\n }\n },\n },\n };\n}\nfunction addHelpers(response) {\n Object.defineProperties(response, getHelpers(response));\n}\nexport function getDPoPHandle(config, keyPair, options) {\n checkConfig(config);\n return oauth.DPoP(int(config).c, keyPair, options);\n}\nasync function handleRetryAfter(response, currentInterval, signal, throwIfInvalid = false) {\n const retryAfter = response.headers.get('retry-after')?.trim();\n if (retryAfter === undefined)\n return;\n let delaySeconds;\n if (/^\\d+$/.test(retryAfter)) {\n delaySeconds = parseInt(retryAfter, 10);\n }\n else {\n const retryDate = new Date(retryAfter);\n if (Number.isFinite(retryDate.getTime())) {\n const now = new Date();\n const delayMs = retryDate.getTime() - now.getTime();\n if (delayMs > 0) {\n delaySeconds = Math.ceil(delayMs / 1000);\n }\n }\n }\n if (throwIfInvalid && !Number.isFinite(delaySeconds)) {\n throw new oauth.OperationProcessingError('invalid Retry-After header value', { cause: response });\n }\n if (delaySeconds > currentInterval) {\n await wait(delaySeconds - currentInterval, signal);\n }\n}\nfunction wait(duration, signal) {\n return new Promise((resolve, reject) => {\n const waitStep = (remaining) => {\n try {\n signal.throwIfAborted();\n }\n catch (err) {\n reject(err);\n return;\n }\n if (remaining <= 0) {\n resolve();\n return;\n }\n const currentWait = Math.min(remaining, 5);\n setTimeout(() => waitStep(remaining - currentWait), currentWait * 1000);\n };\n waitStep(duration);\n });\n}\nexport async function pollDeviceAuthorizationGrant(config, deviceAuthorizationResponse, parameters, options) {\n checkConfig(config);\n parameters = new URLSearchParams(parameters);\n let interval = deviceAuthorizationResponse.interval ?? 5;\n const pollingSignal = options?.signal ??\n AbortSignal.timeout(deviceAuthorizationResponse.expires_in * 1000);\n try {\n await wait(interval, pollingSignal);\n }\n catch (err) {\n errorHandler(err);\n }\n const { as, c, auth, fetch, tlsOnly, nonRepudiation, timeout, decrypt } = int(config);\n const retryPoll = (updatedInterval, flag) => pollDeviceAuthorizationGrant(config, {\n ...deviceAuthorizationResponse,\n interval: updatedInterval,\n }, parameters, {\n ...options,\n signal: pollingSignal,\n flag,\n });\n const response = await oauth\n .deviceCodeGrantRequest(as, c, auth, deviceAuthorizationResponse.device_code, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n additionalParameters: parameters,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n signal: pollingSignal.aborted ? pollingSignal : signal(timeout),\n })\n .catch(errorHandler);\n if (response.status === 503 && response.headers.has('retry-after')) {\n await handleRetryAfter(response, interval, pollingSignal, true);\n await response.body?.cancel();\n return retryPoll(interval);\n }\n const p = oauth.processDeviceCodeResponse(as, c, response, {\n [oauth.jweDecrypt]: decrypt,\n });\n let result;\n try {\n result = await p;\n }\n catch (err) {\n if (retryable(err, options)) {\n return retryPoll(interval, retry);\n }\n if (err instanceof oauth.ResponseBodyError) {\n switch (err.error) {\n case 'slow_down':\n interval += 5;\n case 'authorization_pending':\n await handleRetryAfter(err.response, interval, pollingSignal);\n return retryPoll(interval);\n }\n }\n errorHandler(err);\n }\n result.id_token && (await nonRepudiation?.(response));\n addHelpers(result);\n return result;\n}\nexport async function initiateDeviceAuthorization(config, parameters) {\n checkConfig(config);\n const { as, c, auth, fetch, tlsOnly, timeout } = int(config);\n return oauth\n .deviceAuthorizationRequest(as, c, auth, parameters, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .then((response) => oauth.processDeviceAuthorizationResponse(as, c, response))\n .catch(errorHandler);\n}\nexport async function initiateBackchannelAuthentication(config, parameters) {\n checkConfig(config);\n const { as, c, auth, fetch, tlsOnly, timeout } = int(config);\n return oauth\n .backchannelAuthenticationRequest(as, c, auth, parameters, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .then((response) => oauth.processBackchannelAuthenticationResponse(as, c, response))\n .catch(errorHandler);\n}\nexport async function pollBackchannelAuthenticationGrant(config, backchannelAuthenticationResponse, parameters, options) {\n checkConfig(config);\n parameters = new URLSearchParams(parameters);\n let interval = backchannelAuthenticationResponse.interval ?? 5;\n const pollingSignal = options?.signal ??\n AbortSignal.timeout(backchannelAuthenticationResponse.expires_in * 1000);\n try {\n await wait(interval, pollingSignal);\n }\n catch (err) {\n errorHandler(err);\n }\n const { as, c, auth, fetch, tlsOnly, nonRepudiation, timeout, decrypt } = int(config);\n const retryPoll = (updatedInterval, flag) => pollBackchannelAuthenticationGrant(config, {\n ...backchannelAuthenticationResponse,\n interval: updatedInterval,\n }, parameters, {\n ...options,\n signal: pollingSignal,\n flag,\n });\n const response = await oauth\n .backchannelAuthenticationGrantRequest(as, c, auth, backchannelAuthenticationResponse.auth_req_id, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n additionalParameters: parameters,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n signal: pollingSignal.aborted ? pollingSignal : signal(timeout),\n })\n .catch(errorHandler);\n if (response.status === 503 && response.headers.has('retry-after')) {\n await handleRetryAfter(response, interval, pollingSignal, true);\n await response.body?.cancel();\n return retryPoll(interval);\n }\n const p = oauth.processBackchannelAuthenticationGrantResponse(as, c, response, {\n [oauth.jweDecrypt]: decrypt,\n });\n let result;\n try {\n result = await p;\n }\n catch (err) {\n if (retryable(err, options)) {\n return retryPoll(interval, retry);\n }\n if (err instanceof oauth.ResponseBodyError) {\n switch (err.error) {\n case 'slow_down':\n interval += 5;\n case 'authorization_pending':\n await handleRetryAfter(err.response, interval, pollingSignal);\n return retryPoll(interval);\n }\n }\n errorHandler(err);\n }\n result.id_token && (await nonRepudiation?.(response));\n addHelpers(result);\n return result;\n}\nexport function allowInsecureRequests(config) {\n int(config).tlsOnly = false;\n}\nexport function setJwksCache(config, jwksCache) {\n int(config).jwksCache = structuredClone(jwksCache);\n}\nexport function getJwksCache(config) {\n const cache = int(config).jwksCache;\n if (cache.uat) {\n return cache;\n }\n return undefined;\n}\nexport function enableNonRepudiationChecks(config) {\n checkConfig(config);\n int(config).nonRepudiation = (response) => {\n const { as, fetch, tlsOnly, timeout, jwksCache } = int(config);\n return oauth\n .validateApplicationLevelSignature(as, response, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n headers: new Headers(headers),\n signal: signal(timeout),\n [oauth.jwksCache]: jwksCache,\n })\n .catch(errorHandler);\n };\n}\nexport function useJwtResponseMode(config) {\n checkConfig(config);\n const { hybrid, implicit } = int(config);\n if (hybrid || implicit) {\n throw e('JARM cannot be combined with a hybrid or implicit response types', undefined, oauth.UNSUPPORTED_OPERATION);\n }\n int(config).jarm = (authorizationResponse, expectedState) => validateJARMResponse(config, authorizationResponse, expectedState);\n}\nexport function enableDetachedSignatureResponseChecks(config) {\n if (!int(config).hybrid) {\n throw e('\"code id_token\" response type must be configured to be used first', undefined, oauth.UNSUPPORTED_OPERATION);\n }\n int(config).hybrid = (authorizationResponse, expectedNonce, expectedState, maxAge) => validateCodeIdTokenResponse(config, authorizationResponse, expectedNonce, expectedState, maxAge, true);\n}\nexport async function implicitAuthentication(config, currentUrl, expectedNonce, checks) {\n checkConfig(config);\n if (!(currentUrl instanceof URL) &&\n !webInstanceOf(currentUrl, 'Request')) {\n throw CodedTypeError('\"currentUrl\" must be an instance of URL, or Request', ERR_INVALID_ARG_TYPE);\n }\n if (typeof expectedNonce !== 'string') {\n throw CodedTypeError('\"expectedNonce\" must be a string', ERR_INVALID_ARG_TYPE);\n }\n const { as, c, fetch, tlsOnly, timeout, decrypt, implicit, jwksCache } = int(config);\n if (!implicit) {\n throw new TypeError('implicitAuthentication() cannot be used by clients using flows other than response_type=id_token');\n }\n let params;\n if (!(currentUrl instanceof URL)) {\n const request = currentUrl;\n switch (request.method) {\n case 'GET':\n params = new URLSearchParams(new URL(request.url).hash.slice(1));\n break;\n case 'POST':\n params = new URLSearchParams(await oauth.formPostResponse(request));\n break;\n default:\n throw CodedTypeError('unexpected Request HTTP method', ERR_INVALID_ARG_VALUE);\n }\n }\n else {\n params = new URLSearchParams(currentUrl.hash.slice(1));\n }\n try {\n {\n const decoy = new URLSearchParams(params);\n decoy.delete('id_token');\n oauth.validateAuthResponse({\n ...as,\n authorization_response_iss_parameter_supported: undefined,\n }, c, decoy, checks?.expectedState);\n }\n {\n const decoy = new Response(JSON.stringify({\n access_token: 'decoy',\n token_type: 'bearer',\n id_token: params.get('id_token'),\n }), {\n headers: new Headers({ 'content-type': 'application/json' }),\n });\n const ref = await oauth.processAuthorizationCodeResponse(as, c, decoy, {\n expectedNonce,\n maxAge: checks?.maxAge,\n [oauth.jweDecrypt]: decrypt,\n });\n await oauth.validateApplicationLevelSignature(as, decoy, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n headers: new Headers(headers),\n signal: signal(timeout),\n [oauth.jwksCache]: jwksCache,\n });\n return oauth.getValidatedIdTokenClaims(ref);\n }\n }\n catch (err) {\n errorHandler(err);\n }\n}\nexport function useCodeIdTokenResponseType(config) {\n checkConfig(config);\n const { jarm, implicit } = int(config);\n if (jarm || implicit) {\n throw e('\"code id_token\" response type cannot be combined with JARM or implicit response type', undefined, oauth.UNSUPPORTED_OPERATION);\n }\n int(config).hybrid = (authorizationResponse, expectedNonce, expectedState, maxAge) => validateCodeIdTokenResponse(config, authorizationResponse, expectedNonce, expectedState, maxAge, false);\n}\nexport function useIdTokenResponseType(config) {\n checkConfig(config);\n const { jarm, hybrid } = int(config);\n if (jarm || hybrid) {\n throw e('\"id_token\" response type cannot be combined with JARM or hybrid response type', undefined, oauth.UNSUPPORTED_OPERATION);\n }\n int(config).implicit = true;\n}\nfunction stripParams(url) {\n url = new URL(url);\n url.search = '';\n url.hash = '';\n return url.href;\n}\nfunction webInstanceOf(input, toStringTag) {\n try {\n return Object.getPrototypeOf(input)[Symbol.toStringTag] === toStringTag;\n }\n catch {\n return false;\n }\n}\nexport async function authorizationCodeGrant(config, currentUrl, checks, tokenEndpointParameters, options) {\n checkConfig(config);\n if (options?.flag !== retry &&\n !(currentUrl instanceof URL) &&\n !webInstanceOf(currentUrl, 'Request')) {\n throw CodedTypeError('\"currentUrl\" must be an instance of URL, or Request', ERR_INVALID_ARG_TYPE);\n }\n let authResponse;\n let redirectUri;\n const { as, c, auth, fetch, tlsOnly, jarm, hybrid, nonRepudiation, timeout, decrypt, implicit } = int(config);\n if (options?.flag === retry) {\n authResponse = options.authResponse;\n redirectUri = options.redirectUri;\n }\n else {\n if (!(currentUrl instanceof URL)) {\n const request = currentUrl;\n currentUrl = new URL(currentUrl.url);\n switch (request.method) {\n case 'GET':\n break;\n case 'POST':\n const params = new URLSearchParams(await oauth.formPostResponse(request));\n if (hybrid) {\n currentUrl.hash = params.toString();\n }\n else {\n for (const [k, v] of params.entries()) {\n currentUrl.searchParams.append(k, v);\n }\n }\n break;\n default:\n throw CodedTypeError('unexpected Request HTTP method', ERR_INVALID_ARG_VALUE);\n }\n }\n redirectUri = stripParams(currentUrl);\n switch (true) {\n case !!jarm:\n authResponse = await jarm(currentUrl, checks?.expectedState);\n break;\n case !!hybrid:\n authResponse = await hybrid(currentUrl, checks?.expectedNonce, checks?.expectedState, checks?.maxAge);\n break;\n case !!implicit:\n throw new TypeError('authorizationCodeGrant() cannot be used by response_type=id_token clients');\n default:\n try {\n authResponse = oauth.validateAuthResponse(as, c, currentUrl.searchParams, checks?.expectedState);\n }\n catch (err) {\n errorHandler(err);\n }\n }\n }\n const response = await oauth\n .authorizationCodeGrantRequest(as, c, auth, authResponse, redirectUri, checks?.pkceCodeVerifier || oauth.nopkce, {\n additionalParameters: tokenEndpointParameters,\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .catch(errorHandler);\n if (typeof checks?.expectedNonce === 'string' ||\n typeof checks?.maxAge === 'number') {\n checks.idTokenExpected = true;\n }\n const p = oauth.processAuthorizationCodeResponse(as, c, response, {\n expectedNonce: checks?.expectedNonce,\n maxAge: checks?.maxAge,\n requireIdToken: checks?.idTokenExpected,\n [oauth.jweDecrypt]: decrypt,\n });\n let result;\n try {\n result = await p;\n }\n catch (err) {\n if (retryable(err, options)) {\n return authorizationCodeGrant(config, undefined, checks, tokenEndpointParameters, {\n ...options,\n flag: retry,\n authResponse: authResponse,\n redirectUri: redirectUri,\n });\n }\n errorHandler(err);\n }\n result.id_token && (await nonRepudiation?.(response));\n addHelpers(result);\n return result;\n}\nasync function validateJARMResponse(config, authorizationResponse, expectedState) {\n const { as, c, fetch, tlsOnly, timeout, decrypt, jwksCache } = int(config);\n return oauth\n .validateJwtAuthResponse(as, c, authorizationResponse, expectedState, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n headers: new Headers(headers),\n signal: signal(timeout),\n [oauth.jweDecrypt]: decrypt,\n [oauth.jwksCache]: jwksCache,\n })\n .catch(errorHandler);\n}\nasync function validateCodeIdTokenResponse(config, authorizationResponse, expectedNonce, expectedState, maxAge, fapi) {\n if (typeof expectedNonce !== 'string') {\n throw CodedTypeError('\"expectedNonce\" must be a string', ERR_INVALID_ARG_TYPE);\n }\n if (expectedState !== undefined && typeof expectedState !== 'string') {\n throw CodedTypeError('\"expectedState\" must be a string', ERR_INVALID_ARG_TYPE);\n }\n const { as, c, fetch, tlsOnly, timeout, decrypt, jwksCache } = int(config);\n return (fapi\n ? oauth.validateDetachedSignatureResponse\n : oauth.validateCodeIdTokenResponse)(as, c, authorizationResponse, expectedNonce, expectedState, maxAge, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n headers: new Headers(headers),\n signal: signal(timeout),\n [oauth.jweDecrypt]: decrypt,\n [oauth.jwksCache]: jwksCache,\n }).catch(errorHandler);\n}\nexport async function refreshTokenGrant(config, refreshToken, parameters, options) {\n checkConfig(config);\n parameters = new URLSearchParams(parameters);\n const { as, c, auth, fetch, tlsOnly, nonRepudiation, timeout, decrypt } = int(config);\n const response = await oauth\n .refreshTokenGrantRequest(as, c, auth, refreshToken, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n additionalParameters: parameters,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .catch(errorHandler);\n const p = oauth.processRefreshTokenResponse(as, c, response, {\n [oauth.jweDecrypt]: decrypt,\n });\n let result;\n try {\n result = await p;\n }\n catch (err) {\n if (retryable(err, options)) {\n return refreshTokenGrant(config, refreshToken, parameters, {\n ...options,\n flag: retry,\n });\n }\n errorHandler(err);\n }\n result.id_token && (await nonRepudiation?.(response));\n addHelpers(result);\n return result;\n}\nexport async function clientCredentialsGrant(config, parameters, options) {\n checkConfig(config);\n parameters = new URLSearchParams(parameters);\n const { as, c, auth, fetch, tlsOnly, timeout } = int(config);\n const response = await oauth\n .clientCredentialsGrantRequest(as, c, auth, parameters, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .catch(errorHandler);\n const p = oauth.processClientCredentialsResponse(as, c, response);\n let result;\n try {\n result = await p;\n }\n catch (err) {\n if (retryable(err, options)) {\n return clientCredentialsGrant(config, parameters, {\n ...options,\n flag: retry,\n });\n }\n errorHandler(err);\n }\n addHelpers(result);\n return result;\n}\nexport function buildAuthorizationUrl(config, parameters) {\n checkConfig(config);\n const { as, c, tlsOnly, hybrid, jarm, implicit } = int(config);\n const authorizationEndpoint = oauth.resolveEndpoint(as, 'authorization_endpoint', false, tlsOnly);\n parameters = new URLSearchParams(parameters);\n if (!parameters.has('client_id')) {\n parameters.set('client_id', c.client_id);\n }\n if (!parameters.has('request_uri') && !parameters.has('request')) {\n if (!parameters.has('response_type')) {\n parameters.set('response_type', hybrid ? 'code id_token' : implicit ? 'id_token' : 'code');\n }\n if (implicit && !parameters.has('nonce')) {\n throw CodedTypeError('response_type=id_token clients must provide a nonce parameter in their authorization request parameters', ERR_INVALID_ARG_VALUE);\n }\n if (jarm) {\n parameters.set('response_mode', 'jwt');\n }\n }\n for (const [k, v] of parameters.entries()) {\n authorizationEndpoint.searchParams.append(k, v);\n }\n return authorizationEndpoint;\n}\nexport async function buildAuthorizationUrlWithJAR(config, parameters, signingKey, options) {\n checkConfig(config);\n const authorizationEndpoint = buildAuthorizationUrl(config, parameters);\n parameters = authorizationEndpoint.searchParams;\n if (!signingKey) {\n throw CodedTypeError('\"signingKey\" must be provided', ERR_INVALID_ARG_VALUE);\n }\n const { as, c } = int(config);\n const request = await oauth\n .issueRequestObject(as, c, parameters, signingKey, options)\n .catch(errorHandler);\n return buildAuthorizationUrl(config, { request });\n}\nexport async function buildAuthorizationUrlWithPAR(config, parameters, options) {\n checkConfig(config);\n const authorizationEndpoint = buildAuthorizationUrl(config, parameters);\n const { as, c, auth, fetch, tlsOnly, timeout } = int(config);\n const response = await oauth\n .pushedAuthorizationRequest(as, c, auth, authorizationEndpoint.searchParams, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .catch(errorHandler);\n const p = oauth.processPushedAuthorizationResponse(as, c, response);\n let result;\n try {\n result = await p;\n }\n catch (err) {\n if (retryable(err, options)) {\n return buildAuthorizationUrlWithPAR(config, parameters, {\n ...options,\n flag: retry,\n });\n }\n errorHandler(err);\n }\n return buildAuthorizationUrl(config, { request_uri: result.request_uri });\n}\nexport function buildEndSessionUrl(config, parameters) {\n checkConfig(config);\n const { as, c, tlsOnly } = int(config);\n const endSessionEndpoint = oauth.resolveEndpoint(as, 'end_session_endpoint', false, tlsOnly);\n parameters = new URLSearchParams(parameters);\n if (!parameters.has('client_id')) {\n parameters.set('client_id', c.client_id);\n }\n for (const [k, v] of parameters.entries()) {\n endSessionEndpoint.searchParams.append(k, v);\n }\n return endSessionEndpoint;\n}\nfunction checkConfig(input) {\n if (!(input instanceof Configuration)) {\n throw CodedTypeError('\"config\" must be an instance of Configuration', ERR_INVALID_ARG_TYPE);\n }\n if (Object.getPrototypeOf(input) !== Configuration.prototype) {\n throw CodedTypeError('subclassing Configuration is not allowed', ERR_INVALID_ARG_VALUE);\n }\n}\nfunction signal(timeout) {\n return timeout ? AbortSignal.timeout(timeout * 1000) : undefined;\n}\nexport async function fetchUserInfo(config, accessToken, expectedSubject, options) {\n checkConfig(config);\n const { as, c, fetch, tlsOnly, nonRepudiation, timeout, decrypt } = int(config);\n const response = await oauth\n .userInfoRequest(as, c, accessToken, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .catch(errorHandler);\n let exec = oauth.processUserInfoResponse(as, c, expectedSubject, response, {\n [oauth.jweDecrypt]: decrypt,\n });\n let result;\n try {\n result = await exec;\n }\n catch (err) {\n if (retryable(err, options)) {\n return fetchUserInfo(config, accessToken, expectedSubject, {\n ...options,\n flag: retry,\n });\n }\n errorHandler(err);\n }\n oauth.getContentType(response) === 'application/jwt' &&\n (await nonRepudiation?.(response));\n return result;\n}\nfunction retryable(err, options) {\n if (options?.DPoP && options.flag !== retry) {\n return oauth.isDPoPNonceError(err);\n }\n return false;\n}\nexport async function tokenIntrospection(config, token, parameters) {\n checkConfig(config);\n const { as, c, auth, fetch, tlsOnly, nonRepudiation, timeout, decrypt } = int(config);\n const response = await oauth\n .introspectionRequest(as, c, auth, token, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n additionalParameters: new URLSearchParams(parameters),\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .catch(errorHandler);\n const result = await oauth\n .processIntrospectionResponse(as, c, response, {\n [oauth.jweDecrypt]: decrypt,\n })\n .catch(errorHandler);\n oauth.getContentType(response) === 'application/token-introspection+jwt' &&\n (await nonRepudiation?.(response));\n return result;\n}\nconst retry = Symbol();\nexport async function genericGrantRequest(config, grantType, parameters, options) {\n checkConfig(config);\n const { as, c, auth, fetch, tlsOnly, timeout, decrypt } = int(config);\n const result = await oauth\n .genericTokenEndpointRequest(as, c, auth, grantType, new URLSearchParams(parameters), {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n DPoP: options?.DPoP,\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .then((response) => {\n let recognizedTokenTypes;\n if (grantType === 'urn:ietf:params:oauth:grant-type:token-exchange') {\n recognizedTokenTypes = { n_a: () => { } };\n }\n return oauth.processGenericTokenEndpointResponse(as, c, response, {\n [oauth.jweDecrypt]: decrypt,\n recognizedTokenTypes,\n });\n })\n .catch(errorHandler);\n addHelpers(result);\n return result;\n}\nexport async function tokenRevocation(config, token, parameters) {\n checkConfig(config);\n const { as, c, auth, fetch, tlsOnly, timeout } = int(config);\n return oauth\n .revocationRequest(as, c, auth, token, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n additionalParameters: new URLSearchParams(parameters),\n headers: new Headers(headers),\n signal: signal(timeout),\n })\n .then(oauth.processRevocationResponse)\n .catch(errorHandler);\n}\nexport async function fetchProtectedResource(config, accessToken, url, method, body, headers, options) {\n checkConfig(config);\n headers ||= new Headers();\n if (!headers.has('user-agent')) {\n headers.set('user-agent', USER_AGENT);\n }\n const { fetch, tlsOnly, timeout } = int(config);\n const exec = oauth.protectedResourceRequest(accessToken, method, url, headers, body, {\n [oauth.customFetch]: fetch,\n [oauth.allowInsecureRequests]: !tlsOnly,\n DPoP: options?.DPoP,\n signal: signal(timeout),\n });\n let result;\n try {\n result = await exec;\n }\n catch (err) {\n if (retryable(err, options)) {\n return fetchProtectedResource(config, accessToken, url, method, body, headers, {\n ...options,\n flag: retry,\n });\n }\n errorHandler(err);\n }\n return result;\n}\n//# sourceMappingURL=index.js.map","import {\n $inject,\n AlephaError,\n type Async,\n createPrimitive,\n KIND,\n Primitive,\n} from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport {\n type AccessTokenResponse,\n type RealmPrimitive,\n SecurityError,\n SecurityProvider,\n type UserAccount,\n} from \"alepha/security\";\nimport {\n allowInsecureRequests,\n Configuration,\n discovery,\n refreshTokenGrant,\n} from \"openid-client\";\nimport type { OAuth2Profile } from \"../providers/ServerAuthProvider.ts\";\nimport type { Tokens } from \"../schemas/tokensSchema.ts\";\n\n/**\n * Creates an authentication provider primitive for handling user login flows.\n *\n * Supports multiple authentication strategies: credentials (username/password), OAuth2,\n * and OIDC (OpenID Connect). Handles token management, user profile retrieval, and\n * integration with both external identity providers (Auth0, Keycloak) and internal realms.\n *\n * **Authentication Types**: Credentials, OAuth2 (Google, GitHub), OIDC, External providers\n *\n * @example\n * ```ts\n * class AuthProviders {\n * // Internal credentials-based auth\n * credentials = $auth({\n * realm: this.userRealm,\n * credentials: {\n * account: async ({ username, password }) => {\n * return await this.validateUser(username, password);\n * }\n * }\n * });\n *\n * // External OIDC provider\n * keycloak = $auth({\n * oidc: {\n * issuer: \"https://auth.example.com\",\n * clientId: \"my-app\",\n * clientSecret: \"secret\",\n * redirectUri: \"/auth/callback\"\n * }\n * });\n * }\n * ```\n */\nexport const $auth = (options: AuthPrimitiveOptions): AuthPrimitive => {\n return createPrimitive(AuthPrimitive, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type AuthPrimitiveOptions = {\n /**\n * Name of the identity provider.\n * If not provided, it will be derived from the property key.\n */\n name?: string;\n\n /**\n * If true, auth provider will be skipped.\n */\n disabled?: boolean;\n} & (AuthExternal | AuthInternal);\n\n/**\n * When you let an external service handle authentication. (e.g. Keycloak, Auth0, etc.)\n */\nexport type AuthExternal = {\n /**\n * Only OIDC is supported for external authentication.\n */\n oidc: OidcOptions;\n\n /**\n * For anonymous access, this will expect a service account access token.\n *\n * ```ts\n * class App {\n * anonymous = $serviceAccount(...);\n * auth = $auth({\n * // ... config ...\n * fallback: this.anonymous,\n * })\n * }\n * ```\n */\n fallback?: () => Async<AccessToken>;\n};\n\n/**\n * When using your own authentication system, e.g. using a database to store user accounts.\n * This is usually used with a custom login form.\n *\n * This relies on the `realm`, which is used to create/verify the access token.\n */\nexport type AuthInternal = {\n realm: RealmPrimitive;\n} & (\n | {\n /**\n * The common username/password authentication.\n *\n * - It uses the OAuth2 Client Credentials flow to obtain an access token.\n *\n * This is usually used with a custom login form on your website or mobile app.\n */\n credentials: CredentialsOptions;\n }\n | {\n /**\n * OAuth2 authentication. Delegates authentication to an OAuth2 provider. (e.g. Google, GitHub, etc.)\n *\n * - It uses the OAuth2 Authorization Code flow to obtain an access token and user information.\n *\n * This is usually used with a login button that redirects to the OAuth2 provider.\n */\n oauth: OAuth2Options;\n }\n | {\n /**\n * Like OAuth2, but uses OIDC (OpenID Connect) for authentication and user information retrieval.\n * OIDC is an identity layer on top of OAuth2, providing user authentication and profile information.\n *\n * - It uses the OAuth2 Authorization Code flow to obtain an access token and user information.\n * - PCKE (Proof Key for Code Exchange) is recommended for security.\n *\n * This is usually used with a login button that redirects to the OIDC provider.\n */\n oidc: OidcOptions;\n }\n);\n\nexport type CredentialsOptions = {\n account: CredentialsFn;\n};\n\nexport type CredentialsFn = (\n credentials: Credentials,\n) => Async<UserAccount | undefined>;\n\nexport interface Credentials {\n username: string;\n password: string;\n}\n\nexport interface OidcOptions {\n /**\n * URL of the OIDC issuer.\n */\n issuer: string;\n\n /**\n * Client ID for the OIDC client.\n */\n clientId: string;\n\n /**\n * Client secret for the OIDC client.\n * Optional if PKCE (Proof Key for Code Exchange) is used.\n */\n clientSecret?: string;\n\n /**\n * Redirect URI for the OIDC client.\n * This is where the user will be redirected after authentication.\n */\n redirectUri?: string;\n\n /**\n * For external auth providers only.\n * Take the ID token instead of the access token for validation.\n */\n useIdToken?: boolean;\n\n /**\n * URI to redirect the user after logout.\n */\n logoutUri?: string;\n\n /**\n * Optional scope for the OIDC client.\n * @default \"openid profile email\".\n */\n scope?: string;\n\n account?: LinkAccountFn;\n}\n\nexport interface LinkAccountOptions {\n access_token: string;\n user: OAuth2Profile;\n id_token?: string;\n expires_in?: number;\n scope?: string;\n}\n\nexport type LinkAccountFn = (tokens: LinkAccountOptions) => Async<UserAccount>;\n\nexport interface OAuth2Options {\n /**\n * URL of the OAuth2 authorization endpoint.\n */\n clientId: string;\n\n /**\n * Client secret for the OAuth2 client.\n */\n clientSecret: string;\n\n /**\n * URL of the OAuth2 authorization endpoint.\n */\n authorization: string;\n\n /**\n * URL of the OAuth2 token endpoint.\n */\n token: string;\n\n /**\n * Function to retrieve user profile information from the OAuth2 tokens.\n */\n userinfo: (tokens: Tokens) => Async<OAuth2Profile>;\n\n account?: LinkAccountFn;\n\n /**\n * URL of the OAuth2 authorization endpoint.\n */\n redirectUri?: string;\n\n /**\n * URL of the OAuth2 authorization endpoint.\n */\n scope?: string;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class AuthPrimitive extends Primitive<AuthPrimitiveOptions> {\n protected readonly securityProvider = $inject(SecurityProvider);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n\n public oauth?: Configuration;\n\n public get name() {\n return this.options.name ?? this.config.propertyKey;\n }\n\n public get jwks_uri(): string {\n const jwks = this.oauth?.serverMetadata().jwks_uri;\n if (!jwks) {\n throw new AlephaError(\"No JWKS URI available for the auth provider\");\n }\n return jwks;\n }\n\n public get scope(): string | undefined {\n if (\"oauth\" in this.options) {\n return this.options.oauth.scope;\n }\n if (\"oidc\" in this.options) {\n return this.options.oidc.scope || \"openid profile email\";\n }\n throw new AlephaError(\n \"No OAuth2 or OIDC configuration available for the auth provider\",\n );\n }\n\n public get redirect_uri() {\n if (\"oauth\" in this.options) {\n return this.options.oauth.redirectUri;\n }\n if (\"oidc\" in this.options) {\n return this.options.oidc.redirectUri;\n }\n throw new AlephaError(\n \"No OAuth2 or OIDC configuration available for the auth provider\",\n );\n }\n\n /**\n * Refreshes the access token using the refresh token.\n * Can be used on oauth2, oidc or credentials auth providers.\n */\n public async refresh(\n refreshToken: string,\n accessToken?: string,\n ): Promise<AccessTokenResponse> {\n if (\"realm\" in this.options) {\n return this.options.realm\n .refreshToken(refreshToken, accessToken)\n .then((it) => it.tokens)\n .catch((error) => {\n throw new SecurityError(\n \"Failed to refresh access token using the refresh token (realm)\",\n {\n cause: error,\n },\n );\n });\n } else if (this.oauth) {\n try {\n return {\n ...(await refreshTokenGrant(this.oauth, refreshToken)),\n issued_at: this.dateTimeProvider.now().unix(),\n };\n } catch (error) {\n throw new SecurityError(\n \"Failed to refresh access token using the refresh token (oauth2)\",\n {\n cause: error,\n },\n );\n }\n }\n\n throw new AlephaError(\n \"No realm or OAuth2 configuration available for refreshing the access token\",\n );\n }\n\n /**\n * Extracts user information from the access token.\n * This is used to create a user account from the access token.\n */\n public async user(tokens: Tokens): Promise<UserAccount> {\n try {\n if (\"oauth\" in this.options) {\n const profile = await this.options.oauth.userinfo(tokens);\n\n if (this.options.oauth.account) {\n return this.options.oauth.account({\n ...tokens,\n user: profile,\n });\n }\n\n return this.securityProvider.createUserFromPayload(profile);\n }\n\n if (\"oidc\" in this.options) {\n const payload = this.getUserFromIdToken(tokens.id_token || \"\");\n\n if (this.options.oidc.account) {\n return this.options.oidc.account({\n ...tokens,\n user: payload,\n });\n }\n\n return this.securityProvider.createUserFromPayload(payload);\n }\n } catch (error) {\n throw new SecurityError(\n \"Failed to extract user from identity provider tokens\",\n {\n cause: error,\n },\n );\n }\n\n throw new AlephaError(\n \"This authentication does not support user extraction from tokens\",\n );\n }\n\n protected getUserFromIdToken(idToken: string): OAuth2Profile {\n try {\n return JSON.parse(\n Buffer.from(idToken.split(\".\")[1], \"base64\").toString(\"utf8\"),\n ) as OAuth2Profile;\n } catch (error) {\n throw new AlephaError(\"Failed to parse ID Token payload\", {\n cause: error,\n });\n }\n }\n\n public async prepare() {\n const addons: Array<(config: Configuration) => void> = [];\n\n addons.push(allowInsecureRequests);\n\n if (\"oidc\" in this.options) {\n const { oidc } = this.options;\n\n this.oauth = await discovery(\n new URL(oidc.issuer),\n oidc.clientId,\n {\n client_secret: oidc.clientSecret,\n },\n undefined,\n {\n execute: addons,\n },\n );\n }\n\n if (\"oauth\" in this.options) {\n const { oauth } = this.options;\n\n this.oauth = new Configuration(\n {\n authorization_endpoint: oauth.authorization,\n token_endpoint: oauth.token,\n issuer: oauth.authorization, // use authorization URL as a pseudo-issuer?\n // we don't need all of these endpoints\n jwks_uri: undefined,\n end_session_endpoint: undefined,\n },\n oauth.clientId,\n {\n client_secret: oauth.clientSecret,\n },\n );\n }\n }\n}\n\n$auth[KIND] = AuthPrimitive;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type AccessToken = string | { token: () => Async<string> };\n\nexport interface WithLinkFn {\n link?: (name: string) => (opts: LinkAccountOptions) => Async<UserAccount>;\n}\n\nexport interface WithLoginFn {\n login?: (\n provider: string,\n ) => (creds: Credentials) => Async<UserAccount | undefined>;\n}\n","export const alephaServerAuthRoutes = {\n login: \"/oauth/login\",\n callback: \"/oauth/callback\",\n logout: \"/oauth/logout\",\n token: \"/_auth/token\",\n refresh: \"/_auth/refresh\",\n userinfo: \"/_auth/userinfo\",\n};\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const tokensSchema = t.object({\n provider: t.text(),\n access_token: t.text({ size: \"rich\" }),\n issued_at: t.number(),\n expires_in: t.optional(t.number()),\n refresh_token: t.optional(t.text({ size: \"rich\" })),\n refresh_token_expires_in: t.optional(t.number()),\n refresh_expires_in: t.optional(\n t.number({\n description:\n \"Alias of `refresh_token_expires_in` for compatibility with some providers.\",\n }),\n ),\n id_token: t.optional(t.text({ size: \"rich\" })),\n scope: t.optional(t.text()),\n});\n\nexport type Tokens = Static<typeof tokensSchema>;\n","import { type Static, t } from \"alepha\";\nimport { userAccountInfoSchema } from \"alepha/security\";\nimport { apiLinksResponseSchema } from \"alepha/server/links\";\nimport { tokensSchema } from \"./tokensSchema.ts\";\n\nexport const tokenResponseSchema = t.extend(tokensSchema, {\n user: userAccountInfoSchema,\n api: apiLinksResponseSchema,\n});\n\nexport type TokenResponse = Static<typeof tokenResponseSchema>;\n","import { type Static, t } from \"alepha\";\nimport { userAccountInfoSchema } from \"alepha/security\";\nimport { apiLinksResponseSchema } from \"alepha/server/links\";\n\nexport const userinfoResponseSchema = t.object({\n user: t.optional(userAccountInfoSchema),\n api: apiLinksResponseSchema,\n});\n\nexport type UserinfoResponse = Static<typeof userinfoResponseSchema>;\n","import { $hook, $inject, Alepha, t } from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport {\n InvalidCredentialsError,\n SecurityError,\n type UserAccount,\n} from \"alepha/security\";\nimport { $route, BadRequestError } from \"alepha/server\";\nimport {\n $cookie,\n type Cookies,\n ServerCookiesProvider,\n} from \"alepha/server/cookies\";\nimport { ServerLinksProvider } from \"alepha/server/links\";\nimport {\n authorizationCodeGrant,\n buildAuthorizationUrl,\n buildEndSessionUrl,\n calculatePKCECodeChallenge,\n randomPKCECodeVerifier,\n randomState,\n} from \"openid-client\";\nimport { alephaServerAuthRoutes } from \"../constants/routes.ts\";\nimport { $auth, type AuthPrimitive } from \"../primitives/$auth.ts\";\nimport type { AuthenticationProvider } from \"../schemas/authenticationProviderSchema.ts\";\nimport { tokenResponseSchema } from \"../schemas/tokenResponseSchema.ts\";\nimport { type Tokens, tokensSchema } from \"../schemas/tokensSchema.ts\";\nimport { userinfoResponseSchema } from \"../schemas/userinfoResponseSchema.ts\";\n\nexport class ServerAuthProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly serverCookiesProvider = $inject(ServerCookiesProvider);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly serverLinksProvider = $inject(ServerLinksProvider);\n\n protected readonly authorizationCode = $cookie({\n name: \"authorizationCode\",\n ttl: [15, \"minutes\"],\n httpOnly: true,\n schema: t.object({\n provider: t.text(),\n codeVerifier: t.optional(t.text({ size: \"long\" })),\n redirectUri: t.optional(t.text({ size: \"long\" })),\n state: t.optional(t.text()),\n nonce: t.optional(t.text()),\n }),\n });\n\n public readonly tokens = $cookie({\n name: \"tokens\",\n ttl: [30, \"days\"],\n httpOnly: true,\n compress: true,\n encrypt: true,\n schema: tokensSchema,\n });\n\n public get identities(): Array<AuthPrimitive> {\n return this.alepha\n .primitives($auth)\n .filter((auth) => !auth.options.disabled);\n }\n\n public getAuthenticationProviders(\n filters: { realmName?: string } = {},\n ): AuthenticationProvider[] {\n const providers: AuthenticationProvider[] = [];\n\n for (const identity of this.identities) {\n if (filters.realmName) {\n const realm = \"realm\" in identity.options && identity.options.realm;\n if (!realm || realm.name !== filters.realmName) {\n continue;\n }\n }\n\n const type =\n \"oidc\" in identity.options\n ? \"OIDC\"\n : \"oauth\" in identity.options\n ? \"OAUTH2\"\n : \"credentials\" in identity.options\n ? \"CREDENTIALS\"\n : undefined;\n\n if (!type) {\n continue;\n }\n\n providers.push({\n name: identity.name,\n type,\n });\n }\n\n return providers;\n }\n\n protected readonly configure = $hook({\n on: \"configure\",\n handler: async () => {\n for (const identity of this.identities) {\n await identity.prepare();\n }\n },\n });\n\n protected getAccessTokens(tokens: Tokens) {\n const idp = this.provider(tokens.provider);\n\n if (\n \"oidc\" in idp.options &&\n !(\"realm\" in idp.options) &&\n idp.options.oidc?.useIdToken\n ) {\n return tokens.id_token;\n }\n\n return tokens.access_token;\n }\n\n /**\n * Fill request headers with access token from cookies or fallback to provider's fallback function.\n */\n protected readonly onRequest = $hook({\n on: \"server:onRequest\",\n after: this.serverCookiesProvider,\n handler: async ({ request }) => {\n const cookies = request.cookies;\n\n // [feature] forward cookies to request headers\n if (cookies) {\n const tokens = await this.cookiesToTokens(cookies);\n if (tokens) {\n request.headers.authorization = `Bearer ${this.getAccessTokens(tokens)}`;\n this.log.trace(\"Access token set in request headers\", {\n provider: tokens.provider,\n });\n }\n }\n\n // [feature] support for auth providers with fallback\n if (!request.headers.authorization) {\n for (const provider of this.identities) {\n if (!(\"realm\" in provider.options) && !!provider.options.fallback) {\n const token = await provider.options.fallback();\n if (token) {\n request.headers.authorization = `Bearer ${token}`;\n break;\n }\n }\n }\n }\n },\n });\n\n /**\n * Convert cookies to tokens.\n * If the tokens are expired, try to refresh them using the refresh token.\n */\n protected async cookiesToTokens(\n cookies: Cookies,\n ): Promise<Tokens | undefined> {\n const tokens = this.tokens.get({ cookies });\n if (!tokens) {\n // no cookie, no tokens\n this.log.trace(\"No tokens found in cookies\");\n return;\n }\n\n this.log.trace(\"Tokens found in cookies\", {\n expires_in: tokens.expires_in,\n issued_at: tokens.issued_at,\n });\n\n // check if tokens are expired\n const refreshedTokens = await this.refreshTokens(tokens);\n if (!refreshedTokens) {\n this.tokens.del({ cookies });\n // 08/25: exception here will go to Server error handler, not the React one\n // better to remove cookie & session and let the page handle 401 Unauthorized\n //throw new SessionExpiredError(\"Session expired. Please login again.\");\n return;\n }\n\n if (refreshedTokens.access_token !== tokens.access_token) {\n this.setTokens(refreshedTokens, cookies);\n }\n\n return refreshedTokens;\n }\n\n protected async refreshTokens(tokens: Tokens): Promise<Tokens | undefined> {\n if (tokens.expires_in && tokens.issued_at) {\n const gracePeriodSec = 10;\n const expiresAt = tokens.issued_at + (tokens.expires_in - gracePeriodSec);\n\n if (expiresAt < this.dateTimeProvider.now().unix()) {\n this.log.trace(\"Tokens are expired\");\n\n // oh no, it is expired\n if (tokens.refresh_token) {\n this.log.trace(\"Trying to refresh tokens using refresh token\");\n // but has refresh token!\n try {\n const provider = this.provider(tokens);\n const result = await provider.refresh(\n tokens.refresh_token,\n tokens.access_token,\n );\n const newTokens = {\n ...result,\n provider: tokens.provider,\n issued_at: this.dateTimeProvider.now().unix(),\n };\n\n this.log.debug(\"Tokens refreshed successfully\");\n\n return newTokens;\n } catch (e) {\n this.log.warn(\"Failed to refresh token\", e);\n }\n }\n\n // session expired and no (valid) refresh token\n return;\n }\n }\n\n if (!tokens.issued_at && tokens.access_token) {\n return;\n }\n\n return tokens;\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Get user information.\n */\n public readonly userinfo = $route({\n path: alephaServerAuthRoutes.userinfo,\n schema: {\n response: userinfoResponseSchema,\n },\n handler: async ({ user, headers, cookies }) => {\n const tokens = this.tokens.get({ cookies });\n if (tokens) {\n const provider = this.provider(tokens);\n if (!(\"realm\" in provider.options)) {\n const user = await provider.user(tokens);\n const api = await this.serverLinksProvider.getUserApiLinks({\n authorization: headers.authorization,\n user,\n });\n return {\n api,\n user,\n };\n }\n }\n\n const api = await this.serverLinksProvider.getUserApiLinks({\n authorization: headers.authorization,\n user,\n });\n\n return {\n api,\n user,\n };\n },\n });\n\n /**\n * Refresh a token for internal providers.\n */\n public readonly refresh = $route({\n path: alephaServerAuthRoutes.refresh,\n method: \"POST\",\n schema: {\n query: t.object({\n provider: t.text(),\n }),\n body: t.object({\n refresh_token: t.text({\n size: \"rich\",\n }),\n access_token: t.optional(\n t.text({\n size: \"rich\",\n description:\n \"Required if provider has stateless refresh token on credentials mode\",\n }),\n ),\n }),\n response: tokensSchema,\n },\n handler: async ({ query, body, cookies }) => {\n const provider = this.provider(query);\n\n const tokens = {\n provider: query.provider,\n ...(await provider.refresh(body.refresh_token, body.access_token)),\n };\n\n // for web applications, we store tokens in cookies\n this.setTokens(tokens, cookies);\n\n return tokens;\n },\n });\n\n /**\n * Login for local password-based authentication.\n */\n public readonly token = $route({\n path: alephaServerAuthRoutes.token,\n method: \"POST\",\n schema: {\n query: t.object({\n provider: t.text(),\n }),\n body: t.object({\n username: t.text(),\n password: t.text(),\n }),\n response: tokenResponseSchema,\n },\n handler: async ({ query, body, cookies }) => {\n const provider = this.provider(query);\n const realm = \"realm\" in provider.options && provider.options.realm;\n if (!realm) {\n throw new SecurityError(\n `Auth provider '${query.provider}' does not support password grant`,\n );\n }\n\n const credentials =\n \"credentials\" in provider.options && provider.options.credentials;\n\n if (!credentials) {\n throw new SecurityError(\n `Auth provider '${query.provider}' does not support password grant`,\n );\n }\n\n let user: UserAccount | undefined;\n try {\n user = await credentials.account(body);\n } catch (e) {\n if (e instanceof InvalidCredentialsError) {\n throw e;\n }\n this.log.error(\"Failed to authenticate user\", e);\n throw new InvalidCredentialsError();\n }\n\n if (!user) {\n throw new InvalidCredentialsError();\n }\n\n const tokens = {\n provider: query.provider,\n ...(await realm.createToken(user)),\n };\n\n // for web applications, we store tokens in cookies\n this.setTokens(tokens, cookies);\n\n const api = await this.serverLinksProvider.getUserApiLinks({\n user,\n });\n\n // mobile apps require this\n return {\n ...tokens,\n user,\n api,\n };\n },\n });\n\n /**\n * Oauth2/OIDC login route.\n */\n public readonly login = $route({\n path: alephaServerAuthRoutes.login,\n schema: {\n query: t.object({\n provider: t.text(),\n redirect_uri: t.optional(t.text({ size: \"rich\" })),\n }),\n },\n handler: async ({ query, url, reply }) => {\n const provider = this.provider(query);\n const oauth = provider.oauth;\n if (!oauth) {\n throw new SecurityError(\n `Auth provider '${query.provider}' does not support OAuth2`,\n );\n }\n\n const scope = provider.scope;\n let redirect_uri =\n provider.redirect_uri || alephaServerAuthRoutes.callback;\n if (redirect_uri.startsWith(\"/\")) {\n redirect_uri = `${url.protocol}//${url.host}${redirect_uri}`;\n }\n\n const oidc = \"oidc\" in provider.options && provider.options.oidc;\n\n if (!oauth.serverMetadata().supportsPKCE()) {\n const state = randomState();\n const parameters: Record<string, string> = {\n redirect_uri,\n state,\n };\n\n if (oidc) {\n parameters.nonce = randomState();\n }\n\n if (scope) {\n parameters.scope = scope;\n }\n\n this.authorizationCode.set({\n state,\n nonce: parameters.nonce,\n redirectUri: query.redirect_uri ?? \"/\",\n provider: query.provider,\n });\n\n reply.redirect(buildAuthorizationUrl(oauth, parameters).toString());\n return;\n }\n\n const codeVerifier = randomPKCECodeVerifier();\n const codeChallenge = await calculatePKCECodeChallenge(codeVerifier);\n\n const parameters: Record<string, string> = {\n redirect_uri,\n code_challenge: codeChallenge,\n code_challenge_method: \"S256\",\n };\n\n if (scope) {\n parameters.scope = scope;\n }\n\n this.authorizationCode.set({\n codeVerifier,\n redirectUri: query.redirect_uri ?? \"/\",\n provider: query.provider,\n });\n\n reply.redirect(buildAuthorizationUrl(oauth, parameters).toString());\n },\n });\n\n /**\n * Callback for OAuth2/OIDC providers.\n * It handles the authorization code flow and retrieves the access token.\n */\n public readonly callback = $route({\n path: alephaServerAuthRoutes.callback,\n handler: async ({ url, reply, cookies }) => {\n const authorizationCode = this.authorizationCode.get({ cookies });\n if (!authorizationCode) {\n throw new BadRequestError(\"Missing code verifier\");\n }\n\n const provider = this.provider(authorizationCode);\n const oauth = provider.oauth;\n if (!oauth) {\n throw new SecurityError(\n `Auth provider '${provider.name}' does not support OAuth2`,\n );\n }\n\n const redirectUri = authorizationCode.redirectUri ?? \"/\";\n\n const externalTokens = await authorizationCodeGrant(oauth, url, {\n pkceCodeVerifier: authorizationCode.codeVerifier,\n expectedState: authorizationCode.state,\n expectedNonce: authorizationCode.nonce,\n })\n .then((tokens) => ({\n issued_at: this.dateTimeProvider.now().unix(),\n provider: provider.name,\n ...tokens,\n }))\n .catch((e) => {\n this.log.error(\"Failed to get access token\", e);\n throw new SecurityError(\"Failed to get access token\", {\n cause: e,\n });\n });\n\n this.authorizationCode.del({ cookies });\n\n const realm = \"realm\" in provider.options && provider.options.realm;\n\n // external, full OIDC System (e.g. Keycloak, Auth0)\n if (!realm) {\n this.setTokens(externalTokens, cookies);\n reply.redirect(redirectUri);\n return;\n }\n\n // internal, we need to create our own tokens\n\n const user = await provider.user(externalTokens);\n const tokens = await realm.createToken(user);\n\n this.setTokens(\n {\n ...tokens,\n issued_at: this.dateTimeProvider.now().unix(),\n provider: provider.name,\n },\n cookies,\n );\n\n reply.redirect(redirectUri);\n },\n });\n\n /**\n * Logout route for OAuth2/OIDC providers.\n */\n public readonly logout = $route({\n path: alephaServerAuthRoutes.logout,\n method: \"GET\",\n schema: {\n query: t.object({\n post_logout_redirect_uri: t.optional(t.text()),\n }),\n },\n handler: async ({ query, reply, cookies }) => {\n const redirect = query.post_logout_redirect_uri ?? \"/\";\n const tokens = this.tokens.get({ cookies });\n if (!tokens) {\n reply.redirect(redirect);\n return;\n }\n\n const provider = this.provider(tokens.provider);\n\n this.tokens.del({ cookies });\n\n // for internal providers, we can delete the session - if available\n if (\"realm\" in provider.options && tokens.refresh_token) {\n const onDeleteSession =\n provider.options.realm.options.settings?.onDeleteSession;\n if (onDeleteSession) {\n try {\n await onDeleteSession(tokens.refresh_token);\n } catch (e) {\n this.log.error(\"Failed to delete session\", e);\n }\n }\n }\n\n const oauth = provider.oauth;\n if (!oauth) {\n reply.redirect(redirect);\n return;\n }\n\n const params = new URLSearchParams();\n const idToken = tokens?.id_token;\n\n params.set(\"post_logout_redirect_uri\", redirect);\n if (idToken) {\n params.set(\"id_token_hint\", idToken);\n }\n\n const customLogoutUri =\n \"oidc\" in provider.options\n ? provider.options.oidc?.logoutUri\n : undefined;\n\n if (customLogoutUri) {\n reply.redirect(`${customLogoutUri}?${params}`);\n return;\n }\n\n if (!oauth.serverMetadata().end_session_endpoint) {\n // await tokenRevocation(\n // \toauth,\n // \ttokens?.refresh_token ?? tokens.access_token,\n // );\n reply.redirect(redirect);\n return;\n }\n\n reply.redirect(buildEndSessionUrl(oauth, params).toString());\n },\n });\n\n protected provider(opts: string | { provider: string }): AuthPrimitive {\n const name = typeof opts === \"string\" ? opts : opts.provider;\n const identity = this.identities.find((identity) => identity.name === name);\n\n if (!identity) {\n throw new SecurityError(`Auth provider '${name}' not found`);\n }\n\n return identity;\n }\n\n protected setTokens(tokens: Tokens, cookies?: Cookies): void {\n const exp =\n tokens.refresh_token_expires_in ||\n tokens.refresh_expires_in ||\n tokens.expires_in;\n\n const ttl = exp\n ? this.dateTimeProvider.duration(exp, \"seconds\")\n : undefined;\n\n this.tokens.set(tokens, {\n cookies,\n ttl,\n });\n }\n}\n\nexport interface OAuth2Profile {\n sub: string; // Subject - unique ID per user (required by OpenID)\n email?: string;\n name?: string;\n given_name?: string;\n family_name?: string;\n middle_name?: string;\n nickname?: string;\n preferred_username?: string;\n profile?: string;\n picture?: string;\n website?: string;\n email_verified?: boolean;\n gender?: string;\n birthdate?: string; // ISO 8601: YYYY-MM-DD\n zoneinfo?: string;\n locale?: string;\n phone_number?: string;\n phone_number_verified?: boolean;\n address?: {\n formatted?: string;\n street_address?: string;\n locality?: string;\n region?: string;\n postal_code?: string;\n country?: string;\n };\n updated_at?: number; // seconds since epoch\n // Allow additional fields (provider-specific)\n [key: string]: unknown;\n}\n","import { type Static, t } from \"alepha\";\n\nexport const authenticationProviderSchema = t.object(\n {\n name: t.text({\n description: \"Name of the authentication provider.\",\n }),\n type: t.enum([\"OAUTH2\", \"OIDC\", \"CREDENTIALS\"], {\n description: \"Type of the authentication provider.\",\n }),\n },\n {\n title: \"AuthenticationProvider\",\n },\n);\n\nexport type AuthenticationProvider = Static<\n typeof authenticationProviderSchema\n>;\n","import { AlephaError } from \"alepha\";\nimport type { RealmPrimitive } from \"alepha/security\";\nimport {\n $auth,\n type CredentialsFn,\n type CredentialsOptions,\n type WithLoginFn,\n} from \"./$auth.ts\";\n\n/**\n * Already configured Credentials authentication primitive.\n *\n * Uses username and password to authenticate users.\n */\nexport const $authCredentials = (\n realm: RealmPrimitive & WithLoginFn,\n options: Partial<CredentialsOptions> = {},\n) => {\n const name = \"credentials\";\n\n const account: CredentialsFn | undefined = realm.login\n ? realm.login(name)\n : options.account;\n\n if (!account) {\n throw new AlephaError(\n \"Credentials authentication requires a login function in the realm primitive.\",\n );\n }\n\n return $auth({\n realm,\n name,\n credentials: {\n account,\n },\n });\n};\n","import { $context, AlephaError, t } from \"alepha\";\nimport type { RealmPrimitive } from \"alepha/security\";\nimport type { OAuth2Profile } from \"../providers/ServerAuthProvider.ts\";\nimport {\n $auth,\n type LinkAccountFn,\n type OidcOptions,\n type WithLinkFn,\n} from \"./$auth.ts\";\n\n/**\n * Already configured GitHub authentication primitive.\n *\n * Uses OAuth2 to authenticate users via their GitHub accounts.\n * Upon successful authentication, it links the GitHub account to a user session.\n *\n * Environment Variables:\n * - `GITHUB_CLIENT_ID`: The client ID obtained from the GitHub Developer Settings.\n * - `GITHUB_CLIENT_SECRET`: The client secret obtained from the GitHub Developer Settings.\n */\nexport const $authGithub = (\n realm: RealmPrimitive & WithLinkFn,\n options: Partial<OidcOptions> = {},\n) => {\n const { alepha } = $context();\n\n const env = alepha.parseEnv(\n t.object({\n GITHUB_CLIENT_ID: t.optional(t.text()),\n GITHUB_CLIENT_SECRET: t.optional(t.text()),\n }),\n );\n\n const disabled = !env.GITHUB_CLIENT_ID || !env.GITHUB_CLIENT_SECRET;\n\n const name = \"github\";\n\n const account: LinkAccountFn | undefined =\n options.account ?? (realm.link ? realm.link(name) : undefined);\n\n if (!account) {\n throw new AlephaError(\n \"Authentication requires a link function in the realm primitive.\",\n );\n }\n\n return $auth({\n realm,\n name,\n oauth: {\n clientId: env.GITHUB_CLIENT_ID!,\n clientSecret: env.GITHUB_CLIENT_SECRET!,\n authorization: \"https://github.com/login/oauth/authorize\",\n token: \"https://github.com/login/oauth/access_token\",\n scope: \"read:user user:email\",\n userinfo: async (tokens) => {\n const BASE_URL = \"https://api.github.com\";\n const res = await fetch(`${BASE_URL}/user`, {\n headers: {\n Authorization: `Bearer ${tokens.access_token}`,\n \"User-Agent\": \"Alepha\",\n },\n }).then((res) => res.json());\n\n const user: OAuth2Profile = {\n sub: res.id.toString(),\n };\n\n if (res.email) {\n user.email = res.email;\n }\n\n if (res.name) {\n user.name = res.name.trim();\n }\n\n if (res.avatar_url) {\n user.picture = res.avatar_url;\n }\n\n if (!user.email) {\n const res = await fetch(`${BASE_URL}/user/emails`, {\n headers: {\n Authorization: `Bearer ${tokens.access_token}`,\n \"User-Agent\": \"Alepha\",\n },\n });\n if (res.ok) {\n const emails: any[] = await res.json();\n user.email = (emails.find((e) => e.primary) ?? emails[0]).email;\n }\n }\n\n return user;\n },\n ...options,\n account,\n },\n disabled,\n });\n};\n","import { $context, AlephaError, t } from \"alepha\";\nimport type { RealmPrimitive } from \"alepha/security\";\nimport {\n $auth,\n type LinkAccountFn,\n type OidcOptions,\n type WithLinkFn,\n} from \"./$auth.ts\";\n\n/**\n * Already configured Google authentication primitive.\n *\n * Uses OpenID Connect (OIDC) to authenticate users via their Google accounts.\n * Upon successful authentication, it links the Google account to a user session.\n *\n * Environment Variables:\n * - `GOOGLE_CLIENT_ID`: The client ID obtained from the Google Developer Console.\n * - `GOOGLE_CLIENT_SECRET`: The client secret obtained from the Google Developer Console.\n */\nexport const $authGoogle = (\n realm: RealmPrimitive & WithLinkFn,\n options: Partial<OidcOptions> = {},\n) => {\n const { alepha } = $context();\n\n const env = alepha.parseEnv(\n t.object({\n GOOGLE_CLIENT_ID: t.optional(t.text()),\n GOOGLE_CLIENT_SECRET: t.optional(t.text()),\n }),\n );\n\n const disabled = !env.GOOGLE_CLIENT_ID || !env.GOOGLE_CLIENT_SECRET;\n\n const name = \"google\";\n\n const account: LinkAccountFn | undefined =\n options.account ?? (realm.link ? realm.link(name) : undefined);\n\n if (!account) {\n throw new AlephaError(\n \"Authentication requires a link function in the realm primitive.\",\n );\n }\n\n return $auth({\n realm,\n name,\n oidc: {\n issuer: \"https://accounts.google.com\",\n clientId: env.GOOGLE_CLIENT_ID!,\n clientSecret: env.GOOGLE_CLIENT_SECRET,\n ...options,\n account,\n },\n disabled,\n });\n};\n","import { $module } from \"alepha\";\nimport type { UserAccount } from \"alepha/security\";\nimport { AlephaServerCookies } from \"alepha/server/cookies\";\nimport { $auth } from \"./primitives/$auth.ts\";\nimport { ServerAuthProvider } from \"./providers/ServerAuthProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./index.shared.ts\";\nexport * from \"./primitives/$auth.ts\";\nexport * from \"./primitives/$authCredentials.ts\";\nexport * from \"./primitives/$authGithub.ts\";\nexport * from \"./primitives/$authGoogle.ts\";\nexport * from \"./providers/ServerAuthProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha\" {\n export interface State {\n /**\n * The authenticated user account attached to the server request state.\n *\n * @internal\n */\n \"alepha.server.request.user\"?: UserAccount;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Allow authentication services for server applications.\n * It provides login and logout functionalities.\n *\n * There are multiple authentication providers available (e.g., Google, GitHub).\n * You can also delegate authentication to your own OIDC/OAuth2, for example using Keycloak or Auth0.\n *\n * It's cookie-based and SSR friendly.\n *\n * @see {@link $auth}\n * @see {@link ServerAuthProvider}\n * @module alepha.server.auth\n */\nexport const AlephaServerAuth = $module({\n name: \"alepha.server.auth\",\n primitives: [$auth],\n services: [AlephaServerCookies, ServerAuthProvider],\n});\n"],"x_google_ignoreList":[0,1],"mappings":"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"}