@estifanos-sh/convex-auth 0.0.1-preview.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (387) hide show
  1. package/README.md +52 -0
  2. package/dist/_generated/component.d.ts +2981 -0
  3. package/dist/bin.js +7194 -0
  4. package/dist/browser/index.d.ts +22 -0
  5. package/dist/browser/index.js +61 -0
  6. package/dist/browser/locks.js +20 -0
  7. package/dist/browser/navigation.js +14 -0
  8. package/dist/browser/runtime.js +90 -0
  9. package/dist/browser/webauthn.js +99 -0
  10. package/dist/client/core/types.d.ts +615 -0
  11. package/dist/client/core/types.js +23 -0
  12. package/dist/client/errors.js +30 -0
  13. package/dist/client/factors/device.js +100 -0
  14. package/dist/client/factors/totp.js +111 -0
  15. package/dist/client/factors/webauthn.js +69 -0
  16. package/dist/client/index.d.ts +60 -0
  17. package/dist/client/index.js +976 -0
  18. package/dist/client/runtime/invite.js +50 -0
  19. package/dist/client/runtime/mutex.js +25 -0
  20. package/dist/client/runtime/proxy.js +75 -0
  21. package/dist/client/runtime/storage.js +65 -0
  22. package/dist/component/_generated/api.js +26 -0
  23. package/dist/component/_generated/component.d.ts +2981 -0
  24. package/dist/component/_generated/component.js +1 -0
  25. package/dist/component/_generated/dataModel.js +1 -0
  26. package/dist/component/_generated/server.js +74 -0
  27. package/dist/component/account.js +197 -0
  28. package/dist/component/connection/audit.js +152 -0
  29. package/dist/component/connection/cache.js +205 -0
  30. package/dist/component/connection/domain/verification.js +63 -0
  31. package/dist/component/connection/domain.js +108 -0
  32. package/dist/component/connection/saml/assertion.js +41 -0
  33. package/dist/component/connection/saml/request.js +61 -0
  34. package/dist/component/connection/scim/config.js +55 -0
  35. package/dist/component/connection/scim/identity.js +162 -0
  36. package/dist/component/connection/secret.js +65 -0
  37. package/dist/component/connection/webhook/delivery.js +396 -0
  38. package/dist/component/connection/webhook/endpoint.js +77 -0
  39. package/dist/component/connection.js +204 -0
  40. package/dist/component/convex.config.d.ts +7 -0
  41. package/dist/component/convex.config.js +15 -0
  42. package/dist/component/crons.js +27 -0
  43. package/dist/component/event.js +341 -0
  44. package/dist/component/factor/device.js +141 -0
  45. package/dist/component/factor/passkey.js +385 -0
  46. package/dist/component/factor/totp.js +253 -0
  47. package/dist/component/functions.js +3 -0
  48. package/dist/component/group/active.js +63 -0
  49. package/dist/component/group/invite.js +300 -0
  50. package/dist/component/group/member.js +188 -0
  51. package/dist/component/group.js +431 -0
  52. package/dist/component/http.js +9 -0
  53. package/dist/component/index.d.ts +5 -0
  54. package/dist/component/index.js +3 -0
  55. package/dist/component/limits.js +103 -0
  56. package/dist/component/maintenance.js +205 -0
  57. package/dist/component/migrations.js +277 -0
  58. package/dist/component/model.d.ts +384 -0
  59. package/dist/component/model.js +709 -0
  60. package/dist/component/modules.js +53 -0
  61. package/dist/component/oauth/client.js +196 -0
  62. package/dist/component/oauth/code.js +97 -0
  63. package/dist/component/oauth/refresh.js +230 -0
  64. package/dist/component/schema.d.ts +1530 -0
  65. package/dist/component/schema.js +401 -0
  66. package/dist/component/session.js +134 -0
  67. package/dist/component/token/pkce.js +121 -0
  68. package/dist/component/token/refresh.js +189 -0
  69. package/dist/component/token/verification.js +155 -0
  70. package/dist/component/user/email.js +147 -0
  71. package/dist/component/user/key.js +273 -0
  72. package/dist/component/user.js +173 -0
  73. package/dist/core/index.d.ts +531 -0
  74. package/dist/core/index.js +81 -0
  75. package/dist/expo/index.d.ts +43 -0
  76. package/dist/expo/index.js +131 -0
  77. package/dist/expo/webauthn.js +88 -0
  78. package/dist/node_modules/.pnpm/@opentelemetry_api-logs@0.214.0/node_modules/@opentelemetry/api-logs/build/src/NoopLogger.d.ts +2 -0
  79. package/dist/node_modules/.pnpm/@opentelemetry_api-logs@0.214.0/node_modules/@opentelemetry/api-logs/build/src/api/logs.d.ts +3 -0
  80. package/dist/node_modules/.pnpm/@opentelemetry_api-logs@0.214.0/node_modules/@opentelemetry/api-logs/build/src/index.d.ts +7 -0
  81. package/dist/node_modules/.pnpm/@opentelemetry_api-logs@0.214.0/node_modules/@opentelemetry/api-logs/build/src/types/AnyValue.d.ts +21 -0
  82. package/dist/node_modules/.pnpm/@opentelemetry_api-logs@0.214.0/node_modules/@opentelemetry/api-logs/build/src/types/LogRecord.d.ts +36 -0
  83. package/dist/node_modules/.pnpm/@opentelemetry_api-logs@0.214.0/node_modules/@opentelemetry/api-logs/build/src/types/Logger.d.ts +1 -0
  84. package/dist/node_modules/.pnpm/@opentelemetry_api-logs@0.214.0/node_modules/@opentelemetry/api-logs/build/src/types/LoggerOptions.d.ts +1 -0
  85. package/dist/node_modules/.pnpm/@opentelemetry_api-logs@0.214.0/node_modules/@opentelemetry/api-logs/build/src/types/LoggerProvider.d.ts +2 -0
  86. package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/baggage/propagation/W3CBaggagePropagator.d.ts +1 -0
  87. package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/baggage/utils.d.ts +1 -0
  88. package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/common/attributes.d.ts +1 -0
  89. package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/common/global-error-handler.d.ts +2 -0
  90. package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/common/logging-error-handler.d.ts +1 -0
  91. package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/common/time.d.ts +1 -0
  92. package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/common/types.d.ts +16 -0
  93. package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/index.d.ts +13 -0
  94. package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/propagation/composite.d.ts +1 -0
  95. package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/trace/TraceState.d.ts +1 -0
  96. package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/trace/W3CTraceContextPropagator.d.ts +1 -0
  97. package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/trace/rpc-metadata.d.ts +1 -0
  98. package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/trace/suppress-tracing.d.ts +1 -0
  99. package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/utils/configuration.d.ts +1 -0
  100. package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/LogRecordProcessor.d.ts +24 -0
  101. package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/LoggerProvider.d.ts +2 -0
  102. package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/config/LoggerConfigurators.d.ts +1 -0
  103. package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/export/BatchLogRecordProcessorBase.d.ts +4 -0
  104. package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/export/ConsoleLogRecordExporter.d.ts +3 -0
  105. package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/export/InMemoryLogRecordExporter.d.ts +3 -0
  106. package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/export/LogRecordExporter.d.ts +2 -0
  107. package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/export/ReadableLogRecord.d.ts +4 -0
  108. package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/export/SdkLogRecord.d.ts +71 -0
  109. package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/export/SimpleLogRecordProcessor.d.ts +3 -0
  110. package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/index.d.ts +11 -0
  111. package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/platform/index.d.ts +1 -0
  112. package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/platform/node/export/BatchLogRecordProcessor.d.ts +2 -0
  113. package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/platform/node/index.d.ts +1 -0
  114. package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/types.d.ts +4 -0
  115. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/InstrumentDescriptor.d.ts +3 -0
  116. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/MeterProvider.d.ts +4 -0
  117. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/aggregator/Drop.d.ts +4 -0
  118. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/aggregator/ExponentialHistogram.d.ts +5 -0
  119. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/aggregator/Histogram.d.ts +5 -0
  120. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/aggregator/LastValue.d.ts +5 -0
  121. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/aggregator/Sum.d.ts +5 -0
  122. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/aggregator/index.d.ts +6 -0
  123. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/aggregator/types.d.ts +53 -0
  124. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/AggregationSelector.d.ts +16 -0
  125. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/AggregationTemporality.d.ts +11 -0
  126. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/CardinalitySelector.d.ts +10 -0
  127. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/ConsoleMetricExporter.d.ts +4 -0
  128. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/InMemoryMetricExporter.d.ts +3 -0
  129. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/MetricData.d.ts +148 -0
  130. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/MetricExporter.d.ts +3 -0
  131. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/MetricProducer.d.ts +27 -0
  132. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/MetricReader.d.ts +138 -0
  133. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/PeriodicExportingMetricReader.d.ts +3 -0
  134. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/index.d.ts +15 -0
  135. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/types.d.ts +10 -0
  136. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/utils.d.ts +2 -0
  137. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/view/Aggregation.d.ts +4 -0
  138. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/view/AggregationOption.d.ts +41 -0
  139. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/view/AttributesProcessor.d.ts +1 -0
  140. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/view/InstrumentSelector.d.ts +1 -0
  141. package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/view/View.d.ts +5 -0
  142. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/BasicTracerProvider.d.ts +2 -0
  143. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/IdGenerator.d.ts +11 -0
  144. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/Sampler.d.ts +74 -0
  145. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/Span.d.ts +17 -0
  146. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/SpanProcessor.d.ts +43 -0
  147. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/TimedEvent.d.ts +19 -0
  148. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/export/BatchSpanProcessorBase.d.ts +6 -0
  149. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/export/ConsoleSpanExporter.d.ts +3 -0
  150. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/export/InMemorySpanExporter.d.ts +3 -0
  151. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/export/NoopSpanProcessor.d.ts +4 -0
  152. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/export/ReadableSpan.d.ts +29 -0
  153. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/export/SimpleSpanProcessor.d.ts +5 -0
  154. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/export/SpanExporter.d.ts +2 -0
  155. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/index.d.ts +18 -0
  156. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/platform/index.d.ts +1 -0
  157. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/platform/node/export/BatchSpanProcessor.d.ts +2 -0
  158. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/platform/node/index.d.ts +1 -0
  159. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/sampler/AlwaysOffSampler.d.ts +1 -0
  160. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/sampler/AlwaysOnSampler.d.ts +1 -0
  161. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/sampler/ParentBasedSampler.d.ts +2 -0
  162. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/sampler/TraceIdRatioBasedSampler.d.ts +1 -0
  163. package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/types.d.ts +66 -0
  164. package/dist/otel.d.ts +73 -0
  165. package/dist/otel.js +82 -0
  166. package/dist/permissions/index.d.ts +81 -0
  167. package/dist/permissions/index.js +18 -0
  168. package/dist/providers/anonymous.d.ts +35 -0
  169. package/dist/providers/anonymous.js +40 -0
  170. package/dist/providers/apple.d.ts +61 -0
  171. package/dist/providers/apple.js +57 -0
  172. package/dist/providers/connection.d.ts +30 -0
  173. package/dist/providers/connection.js +33 -0
  174. package/dist/providers/credentials.d.ts +78 -0
  175. package/dist/providers/credentials.js +31 -0
  176. package/dist/providers/custom.d.ts +96 -0
  177. package/dist/providers/custom.js +108 -0
  178. package/dist/providers/device.d.ts +33 -0
  179. package/dist/providers/device.js +30 -0
  180. package/dist/providers/email.d.ts +45 -0
  181. package/dist/providers/email.js +52 -0
  182. package/dist/providers/github.d.ts +56 -0
  183. package/dist/providers/github.js +79 -0
  184. package/dist/providers/google.d.ts +56 -0
  185. package/dist/providers/google.js +59 -0
  186. package/dist/providers/index.d.ts +16 -0
  187. package/dist/providers/index.js +16 -0
  188. package/dist/providers/microsoft.d.ts +59 -0
  189. package/dist/providers/microsoft.js +98 -0
  190. package/dist/providers/password.d.ts +68 -0
  191. package/dist/providers/password.js +348 -0
  192. package/dist/providers/phone.d.ts +33 -0
  193. package/dist/providers/phone.js +35 -0
  194. package/dist/providers/redirect.d.ts +1 -0
  195. package/dist/providers/redirect.js +11 -0
  196. package/dist/providers/totp.d.ts +29 -0
  197. package/dist/providers/totp.js +29 -0
  198. package/dist/providers/webauthn/attestation.d.ts +42 -0
  199. package/dist/providers/webauthn/attestation.js +167 -0
  200. package/dist/providers/webauthn.d.ts +83 -0
  201. package/dist/providers/webauthn.js +57 -0
  202. package/dist/react/index.d.ts +55 -0
  203. package/dist/react/index.js +80 -0
  204. package/dist/server/auth.d.ts +443 -0
  205. package/dist/server/auth.js +178 -0
  206. package/dist/server/cache/context.js +94 -0
  207. package/dist/server/component/api.d.ts +14 -0
  208. package/dist/server/component/api.js +13 -0
  209. package/dist/server/component/context.d.ts +16 -0
  210. package/dist/server/component/context.js +1 -0
  211. package/dist/server/component/factor/db.js +71 -0
  212. package/dist/server/config.d.ts +3 -0
  213. package/dist/server/config.js +78 -0
  214. package/dist/server/connection/config.js +101 -0
  215. package/dist/server/connection/domain.d.ts +878 -0
  216. package/dist/server/connection/domain.js +1122 -0
  217. package/dist/server/connection/group/service.d.ts +25 -0
  218. package/dist/server/connection/group/service.js +250 -0
  219. package/dist/server/connection/http.js +1485 -0
  220. package/dist/server/connection/oidc.js +366 -0
  221. package/dist/server/connection/policy/domain.js +59 -0
  222. package/dist/server/connection/policy.d.ts +1 -0
  223. package/dist/server/connection/policy.js +163 -0
  224. package/dist/server/connection/profile.js +22 -0
  225. package/dist/server/connection/provision.js +182 -0
  226. package/dist/server/connection/saml/api.js +70 -0
  227. package/dist/server/connection/saml/binding/post.js +140 -0
  228. package/dist/server/connection/saml/binding/redirect.js +139 -0
  229. package/dist/server/connection/saml/binding/shared.js +18 -0
  230. package/dist/server/connection/saml/c14n.js +224 -0
  231. package/dist/server/connection/saml/constants.js +100 -0
  232. package/dist/server/connection/saml/crypto.js +170 -0
  233. package/dist/server/connection/saml/dom/select.js +299 -0
  234. package/dist/server/connection/saml/encoding.js +93 -0
  235. package/dist/server/connection/saml/encryption.js +34 -0
  236. package/dist/server/connection/saml/entity.js +24 -0
  237. package/dist/server/connection/saml/extractor.js +408 -0
  238. package/dist/server/connection/saml/flow.js +150 -0
  239. package/dist/server/connection/saml/identity/provider.js +66 -0
  240. package/dist/server/connection/saml/index.js +5 -0
  241. package/dist/server/connection/saml/metadata.js +294 -0
  242. package/dist/server/connection/saml/service/provider.js +117 -0
  243. package/dist/server/connection/saml/signature.js +214 -0
  244. package/dist/server/connection/saml/template.js +68 -0
  245. package/dist/server/connection/saml/types.js +1 -0
  246. package/dist/server/connection/saml/validator.js +32 -0
  247. package/dist/server/connection/saml/xml/builder.js +68 -0
  248. package/dist/server/connection/saml/xmldsig.js +598 -0
  249. package/dist/server/connection/saml/xmlenc.js +162 -0
  250. package/dist/server/connection/saml.d.ts +56 -0
  251. package/dist/server/connection/saml.js +762 -0
  252. package/dist/server/connection/scim.js +115 -0
  253. package/dist/server/connection/shared.js +74 -0
  254. package/dist/server/connection/webhook.js +163 -0
  255. package/dist/server/context.d.ts +137 -0
  256. package/dist/server/context.js +108 -0
  257. package/dist/server/contract.d.ts +48 -0
  258. package/dist/server/contract.js +107 -0
  259. package/dist/server/cookies.js +90 -0
  260. package/dist/server/core.js +163 -0
  261. package/dist/server/cors.d.ts +22 -0
  262. package/dist/server/cors.js +93 -0
  263. package/dist/server/crypto.js +43 -0
  264. package/dist/server/db.js +88 -0
  265. package/dist/server/device.js +140 -0
  266. package/dist/server/domains/access.js +29 -0
  267. package/dist/server/domains/account.d.ts +16 -0
  268. package/dist/server/domains/account.js +92 -0
  269. package/dist/server/domains/factor.d.ts +28 -0
  270. package/dist/server/domains/factor.js +115 -0
  271. package/dist/server/domains/group.js +87 -0
  272. package/dist/server/domains/invite.js +76 -0
  273. package/dist/server/domains/key.js +253 -0
  274. package/dist/server/domains/member.js +149 -0
  275. package/dist/server/domains/session.js +29 -0
  276. package/dist/server/domains/user.js +119 -0
  277. package/dist/server/env.d.ts +46 -0
  278. package/dist/server/env.js +96 -0
  279. package/dist/server/errors.js +38 -0
  280. package/dist/server/events.d.ts +880 -0
  281. package/dist/server/events.js +406 -0
  282. package/dist/server/facade.d.ts +83 -0
  283. package/dist/server/facade.js +124 -0
  284. package/dist/server/http.d.ts +125 -0
  285. package/dist/server/http.js +566 -0
  286. package/dist/server/identity/claims.js +58 -0
  287. package/dist/server/identity/convex.d.ts +15 -0
  288. package/dist/server/identity/convex.js +1 -0
  289. package/dist/server/index.d.ts +17 -0
  290. package/dist/server/index.js +11 -0
  291. package/dist/server/keys.js +60 -0
  292. package/dist/server/limits.js +41 -0
  293. package/dist/server/log.js +28 -0
  294. package/dist/server/mcp.d.ts +19 -0
  295. package/dist/server/mcp.js +250 -0
  296. package/dist/server/mutations/account.js +47 -0
  297. package/dist/server/mutations/calls.js +16 -0
  298. package/dist/server/mutations/code.js +91 -0
  299. package/dist/server/mutations/credentials/signin.js +210 -0
  300. package/dist/server/mutations/invalidate.js +60 -0
  301. package/dist/server/mutations/oauth.js +251 -0
  302. package/dist/server/mutations/refresh.js +152 -0
  303. package/dist/server/mutations/register.js +93 -0
  304. package/dist/server/mutations/retrieve.js +66 -0
  305. package/dist/server/mutations/signature.js +36 -0
  306. package/dist/server/mutations/signin.js +81 -0
  307. package/dist/server/mutations/signout.js +61 -0
  308. package/dist/server/mutations/store/refs.js +15 -0
  309. package/dist/server/mutations/store.js +82 -0
  310. package/dist/server/mutations/verifier.js +25 -0
  311. package/dist/server/mutations/verify.js +199 -0
  312. package/dist/server/oauth/authorize.js +98 -0
  313. package/dist/server/oauth/client.d.ts +93 -0
  314. package/dist/server/oauth/client.js +115 -0
  315. package/dist/server/oauth/code.d.ts +63 -0
  316. package/dist/server/oauth/code.js +124 -0
  317. package/dist/server/oauth/domain.d.ts +23 -0
  318. package/dist/server/oauth/domain.js +1 -0
  319. package/dist/server/oauth/factory.js +46 -0
  320. package/dist/server/oauth/grant.js +46 -0
  321. package/dist/server/oauth/handlers.js +108 -0
  322. package/dist/server/oauth/manage.js +121 -0
  323. package/dist/server/oauth/normalize.js +27 -0
  324. package/dist/server/oauth/refresh.d.ts +71 -0
  325. package/dist/server/oauth/refresh.js +132 -0
  326. package/dist/server/oauth/register.js +147 -0
  327. package/dist/server/oauth/runtime.js +280 -0
  328. package/dist/server/oauth/token.js +355 -0
  329. package/dist/server/payloads.d.ts +16 -0
  330. package/dist/server/payloads.js +30 -0
  331. package/dist/server/preload.d.ts +249 -0
  332. package/dist/server/preload.js +673 -0
  333. package/dist/server/random.js +25 -0
  334. package/dist/server/redirects.js +85 -0
  335. package/dist/server/runtime.d.ts +845 -0
  336. package/dist/server/runtime.js +387 -0
  337. package/dist/server/secret.js +46 -0
  338. package/dist/server/services/factors.js +117 -0
  339. package/dist/server/services/providers.js +23 -0
  340. package/dist/server/services/resolve.js +17 -0
  341. package/dist/server/session/lifecycle.d.ts +23 -0
  342. package/dist/server/session/lifecycle.js +139 -0
  343. package/dist/server/signin/flow.js +359 -0
  344. package/dist/server/telemetry.js +68 -0
  345. package/dist/server/templates.js +91 -0
  346. package/dist/server/token/refresh.js +35 -0
  347. package/dist/server/tokens.js +164 -0
  348. package/dist/server/totp.js +282 -0
  349. package/dist/server/types.d.ts +1154 -0
  350. package/dist/server/types.js +1 -0
  351. package/dist/server/url.js +43 -0
  352. package/dist/server/user/account.js +325 -0
  353. package/dist/server/utils/bearer.js +24 -0
  354. package/dist/server/utils/cache.js +51 -0
  355. package/dist/server/utils/retry.js +3 -0
  356. package/dist/server/utils/span.js +59 -0
  357. package/dist/server/validators.d.ts +2061 -0
  358. package/dist/server/validators.js +320 -0
  359. package/dist/server/webauthn.js +699 -0
  360. package/dist/server/wellknown.d.ts +74 -0
  361. package/dist/server/wellknown.js +195 -0
  362. package/dist/shared/brand.d.ts +28 -0
  363. package/dist/shared/brand.js +13 -0
  364. package/dist/shared/codes.d.ts +99 -0
  365. package/dist/shared/codes.js +98 -0
  366. package/dist/shared/compare.js +23 -0
  367. package/dist/shared/errors.js +24 -0
  368. package/dist/shared/event/kinds.d.ts +188 -0
  369. package/dist/shared/event/kinds.js +103 -0
  370. package/dist/shared/fetch/guard.js +189 -0
  371. package/dist/shared/log.js +62 -0
  372. package/dist/shared/results.d.ts +58 -0
  373. package/dist/shared/retry.js +27 -0
  374. package/dist/shared/webauthn.js +9 -0
  375. package/dist/svelte/AuthLoading.svelte +13 -0
  376. package/dist/svelte/AuthLoading.svelte.d.ts +8 -0
  377. package/dist/svelte/SignedIn.svelte +14 -0
  378. package/dist/svelte/SignedIn.svelte.d.ts +8 -0
  379. package/dist/svelte/SignedOut.svelte +13 -0
  380. package/dist/svelte/SignedOut.svelte.d.ts +8 -0
  381. package/dist/svelte/context.svelte.d.ts +26 -0
  382. package/dist/svelte/context.svelte.js +61 -0
  383. package/dist/svelte/index.d.ts +5 -0
  384. package/dist/svelte/index.js +4 -0
  385. package/dist/test.d.ts +48 -0
  386. package/dist/test.js +54 -0
  387. package/package.json +247 -0
@@ -0,0 +1,762 @@
1
+ import { log } from "../log.js";
2
+ import { finalizeNormalizedProfile, normalizeStringArray } from "./profile.js";
3
+ import { asRecord, getGroupSamlUrls } from "./shared.js";
4
+ import { getSamlConfig } from "./config.js";
5
+ import { BINDING_URI, DEFAULT_MAX_SAML_METADATA_SIZE, DEFAULT_MAX_SAML_RESPONSE_SIZE } from "./saml/constants.js";
6
+ import { safeParseXml, setSchemaValidator } from "./saml/api.js";
7
+ import { createIdentityProvider } from "./saml/identity/provider.js";
8
+ import { createServiceProvider } from "./saml/service/provider.js";
9
+ import { decodeBase64urlIgnorePadding, encodeBase64urlNoPadding } from "@oslojs/encoding";
10
+
11
+ //#region src/server/connection/saml.ts
12
+ function formDataEntries(formData) {
13
+ return formData.entries();
14
+ }
15
+ const _samlifyPermissiveValidator = { validate: (_xml) => Promise.resolve("OK") };
16
+ /**
17
+ * Register the SAML schema validator before parsing any SAML response.
18
+ *
19
+ * A permissive validator that always resolves is used because Convex's edge
20
+ * runtime has no file-system access for XML schema files, and structural
21
+ * correctness is already ensured by the XML parser. This is called directly
22
+ * before each parse operation since Convex can restart the V8 isolate between
23
+ * requests, resetting module-level state.
24
+ */
25
+ function ensureSamlifyValidator() {
26
+ setSchemaValidator(_samlifyPermissiveValidator);
27
+ }
28
+ function escapeHtmlAttribute(value) {
29
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
30
+ }
31
+ /**
32
+ * Build an auto-submitting HTML form that POSTs a SAML message to the IdP/SP
33
+ * endpoint (HTTP-POST binding). All interpolated values are HTML-attribute
34
+ * escaped to prevent markup injection.
35
+ * @internal
36
+ */
37
+ function createSamlPostBindingResponse(opts) {
38
+ const fields = [`<input type="hidden" name="${opts.parameter}" value="${escapeHtmlAttribute(opts.value)}" />`, opts.relayState ? `<input type="hidden" name="RelayState" value="${escapeHtmlAttribute(opts.relayState)}" />` : ""].join("");
39
+ return new Response(`<!doctype html><html><body><form method="POST" action="${escapeHtmlAttribute(opts.endpoint)}">${fields}</form><script>document.forms[0].submit();<\/script></body></html>`, {
40
+ status: 200,
41
+ headers: { "Content-Type": "text/html; charset=utf-8" }
42
+ });
43
+ }
44
+ /**
45
+ * Decode a base64url RelayState into its JSON object, returning `{}` on any
46
+ * decode/parse failure.
47
+ * @internal
48
+ */
49
+ function decodeRelayState(value) {
50
+ if (!value) return {};
51
+ try {
52
+ return JSON.parse(new TextDecoder().decode(decodeBase64urlIgnorePadding(value)));
53
+ } catch {
54
+ return {};
55
+ }
56
+ }
57
+ /**
58
+ * Encode a group connection's SAML RelayState (source, signature, requestId,
59
+ * state, redirectTo) as a base64url JSON string.
60
+ * @internal
61
+ */
62
+ function encodeGroupSamlRelayState(value) {
63
+ return encodeBase64urlNoPadding(new TextEncoder().encode(JSON.stringify({
64
+ source: `${value.source.kind}:${value.source.id}`,
65
+ signature: value.signature,
66
+ requestId: value.requestId,
67
+ state: value.state,
68
+ redirectTo: value.redirectTo
69
+ })));
70
+ }
71
+ /**
72
+ * Decode and validate a group connection's SAML RelayState, throwing if it is
73
+ * missing, malformed, or not a `connection:<id>` source.
74
+ * @internal
75
+ */
76
+ function decodeGroupSamlRelayStateOrThrow(value) {
77
+ if (!value) throw new Error("Missing SAML RelayState.");
78
+ const decoded = decodeRelayState(value);
79
+ if (typeof decoded.source !== "string" || typeof decoded.signature !== "string" || typeof decoded.requestId !== "string" || typeof decoded.state !== "string") throw new Error("Invalid SAML RelayState.");
80
+ const [kind, ...rest] = decoded.source.split(":");
81
+ const id = rest.join(":");
82
+ if (kind !== "connection" || id.length === 0) throw new Error("Invalid group connection SAML source.");
83
+ return {
84
+ source: {
85
+ kind,
86
+ id
87
+ },
88
+ signature: decoded.signature,
89
+ requestId: decoded.requestId,
90
+ state: decoded.state,
91
+ redirectTo: typeof decoded.redirectTo === "string" ? decoded.redirectTo : void 0
92
+ };
93
+ }
94
+ /**
95
+ * Read a form-encoded (urlencoded or multipart) request body into a flat
96
+ * string map; returns `{}` for any other content type.
97
+ * @internal
98
+ */
99
+ async function readRequestBody(request) {
100
+ const contentType = request.headers.get("Content-Type") ?? "";
101
+ if (contentType.includes("application/x-www-form-urlencoded") || contentType.includes("multipart/form-data")) {
102
+ const form = await request.formData();
103
+ const body = {};
104
+ for (const [key, value] of formDataEntries(form)) body[key] = typeof value === "string" ? value : value.name;
105
+ return body;
106
+ }
107
+ return {};
108
+ }
109
+ /**
110
+ * Normalize an incoming SAML HTTP request into a {@link GroupSamlHttpRequest},
111
+ * resolving the binding (redirect vs post) and extracting RelayState and the
112
+ * presence of SAMLRequest/SAMLResponse from query or body.
113
+ * @internal
114
+ */
115
+ async function readGroupConnectionSamlHttpRequest(request) {
116
+ const url = new URL(request.url);
117
+ const body = await readRequestBody(request);
118
+ return {
119
+ url,
120
+ body,
121
+ query: Object.fromEntries(url.searchParams),
122
+ binding: request.method === "GET" ? "redirect" : body.SAMLResponse || body.SAMLRequest ? "post" : "redirect",
123
+ relayState: body.RelayState ?? url.searchParams.get("RelayState") ?? void 0,
124
+ hasSamlRequest: Boolean(body.SAMLRequest ?? url.searchParams.get("SAMLRequest")),
125
+ hasSamlResponse: Boolean(body.SAMLResponse ?? url.searchParams.get("SAMLResponse"))
126
+ };
127
+ }
128
+ function getSamlSecurityConfig(config) {
129
+ return getSamlConfig(config).security ?? {};
130
+ }
131
+ /**
132
+ * Parse IdP SAML metadata XML into a {@link ParsedSamlMetadata} (entityID,
133
+ * SSO/SLO bindings, signing/encryption certs, NameID formats).
134
+ *
135
+ * Rejects metadata containing DTD or entity declarations to prevent XXE /
136
+ * entity-expansion attacks against the downstream XML parser.
137
+ * @internal
138
+ */
139
+ function parseSamlIdpMetadata(metadata) {
140
+ const source = typeof metadata === "string" ? metadata : String(metadata);
141
+ if (/<!DOCTYPE|<!ENTITY/i.test(source)) throw new Error("SAML metadata must not contain DTD or entity declarations.");
142
+ const entityId = source.match(/<[^>]*EntityDescriptor\b[^>]*\bentityID="([^"]+)"/i)?.[1] ?? null;
143
+ if (!entityId) throw new Error("SAML metadata is missing EntityDescriptor@entityID.");
144
+ const parseAttributes = (source$1) => {
145
+ const attributes = {};
146
+ for (const match of source$1.matchAll(/([A-Za-z_:][\w:.-]*)="([^"]*)"/g)) attributes[match[1]] = match[2];
147
+ return attributes;
148
+ };
149
+ const readServiceBindings = (tagName) => {
150
+ const bindings = {};
151
+ const pattern = new RegExp(`<(?:[A-Za-z0-9_.-]+:)?${tagName}\\b([^>]*)\\/?>(?:<\\/(?:[A-Za-z0-9_.-]+:)?${tagName}>)?`, "gi");
152
+ for (const match of source.matchAll(pattern)) {
153
+ const attrs = parseAttributes(match[1] ?? "");
154
+ const binding = attrs.Binding ?? attrs.binding;
155
+ const location = attrs.Location ?? attrs.location;
156
+ if (!binding || !location) continue;
157
+ if (binding.includes("HTTP-Redirect")) bindings.redirect = location;
158
+ if (binding.includes("HTTP-POST")) bindings.post = location;
159
+ }
160
+ return bindings;
161
+ };
162
+ const readCertificates = (use) => {
163
+ const certs = [];
164
+ const blockPattern = new RegExp(`<(?:[A-Za-z0-9_.-]+:)?KeyDescriptor\\b([^>]*)>([\\s\\S]*?)<\\/(?:[A-Za-z0-9_.-]+:)?KeyDescriptor>`, "gi");
165
+ for (const match of source.matchAll(blockPattern)) {
166
+ const attrs = parseAttributes(match[1] ?? "");
167
+ if ((attrs.use ?? attrs.Use ?? "signing").toLowerCase() !== use) continue;
168
+ for (const certMatch of (match[2] ?? "").matchAll(/<(?:[A-Za-z0-9_.-]+:)?X509Certificate\b[^>]*>([\s\S]*?)<\/(?:[A-Za-z0-9_.-]+:)?X509Certificate>/gi)) {
169
+ const certificate = certMatch[1]?.replace(/\s+/g, "").trim();
170
+ if (certificate) certs.push(certificate);
171
+ }
172
+ }
173
+ if (certs.length === 0) return null;
174
+ return certs.length === 1 ? certs[0] : certs;
175
+ };
176
+ const nameIdFormats = [...source.matchAll(/<(?:[A-Za-z0-9_.-]+:)?NameIDFormat>([\s\S]*?)<\/(?:[A-Za-z0-9_.-]+:)?NameIDFormat>/gi)].map((match) => match[1]?.trim()).filter((value) => Boolean(value));
177
+ return {
178
+ entityId,
179
+ issuer: entityId,
180
+ connection: readServiceBindings("SingleSignOnService"),
181
+ slo: readServiceBindings("SingleLogoutService"),
182
+ signingCert: readCertificates("signing"),
183
+ encryptionCert: readCertificates("encryption"),
184
+ nameIdFormats,
185
+ wantsSignedAuthnRequests: /WantAuthnRequestsSigned="(?:true|1)"/i.test(source)
186
+ };
187
+ }
188
+ /**
189
+ * Throw if the IdP metadata XML exceeds the connection's configured
190
+ * `maxMetadataSize`, bounding parser work against oversized payloads.
191
+ *
192
+ * When no limit is configured a generous default
193
+ * ({@link DEFAULT_MAX_SAML_METADATA_SIZE}) applies so the cap is never silently
194
+ * off; an operator may override it per connection or disable it entirely with a
195
+ * non-positive value.
196
+ * @internal
197
+ */
198
+ function enforceSamlMetadataSize(opts) {
199
+ const configured = getSamlSecurityConfig(opts.config).maxMetadataSize;
200
+ const maxMetadataSize = typeof configured === "number" ? configured : DEFAULT_MAX_SAML_METADATA_SIZE;
201
+ if (maxMetadataSize > 0 && opts.metadataXml.length > maxMetadataSize) throw new Error("SAML metadata exceeds the configured size limit.");
202
+ }
203
+ /**
204
+ * Size-check then parse IdP metadata: {@link enforceSamlMetadataSize} followed
205
+ * by {@link parseSamlIdpMetadata}.
206
+ * @internal
207
+ */
208
+ function parseSamlIdpMetadataChecked(opts) {
209
+ enforceSamlMetadataSize(opts);
210
+ return parseSamlIdpMetadata(opts.metadataXml);
211
+ }
212
+ /**
213
+ * Throw if the encoded SAMLResponse exceeds the connection's configured
214
+ * `maxResponseSize`, bounding decode/parse work against oversized payloads.
215
+ *
216
+ * The ACS handler base64-decodes and DOM-parses the response *before* verifying
217
+ * its signature, so this runs on unauthenticated input. When no limit is
218
+ * configured a generous default ({@link DEFAULT_MAX_SAML_RESPONSE_SIZE}) applies
219
+ * so the pre-auth parser can never be handed an unbounded document; an operator
220
+ * may override it per connection or disable it with a non-positive value.
221
+ * @internal
222
+ */
223
+ function enforceSamlResponseSize(opts) {
224
+ const configured = getSamlSecurityConfig(opts.config).maxResponseSize;
225
+ const maxResponseSize = typeof configured === "number" ? configured : DEFAULT_MAX_SAML_RESPONSE_SIZE;
226
+ if (maxResponseSize <= 0) return;
227
+ const encoded = opts.request.body.SAMLResponse ?? opts.request.query.SAMLResponse;
228
+ if (typeof encoded === "string" && encoded.length > maxResponseSize) throw new Error("SAML response exceeds the configured size limit.");
229
+ }
230
+ /**
231
+ * Build the SP's SAML metadata XML (entityID, ACS/SLO endpoints, signing and
232
+ * encryption certs) for publication to the IdP.
233
+ * @internal
234
+ */
235
+ function createServiceProviderMetadata(opts) {
236
+ const binding = BINDING_URI;
237
+ return createServiceProvider({
238
+ entityID: opts.entityId,
239
+ authnRequestsSigned: opts.authnRequestsSigned ?? false,
240
+ privateKey: opts.privateKey,
241
+ privateKeyPass: opts.privateKeyPass,
242
+ signingCert: opts.signingCert,
243
+ encryptCert: opts.encryptCert,
244
+ encPrivateKey: opts.encPrivateKey,
245
+ encPrivateKeyPass: opts.encPrivateKeyPass,
246
+ assertionConsumerService: [{
247
+ Binding: binding.post,
248
+ Location: opts.acsUrl
249
+ }],
250
+ singleLogoutService: opts.sloUrl ? [{
251
+ Binding: binding.redirect,
252
+ Location: opts.sloUrl
253
+ }, {
254
+ Binding: binding.post,
255
+ Location: opts.sloUrl
256
+ }] : void 0
257
+ }).getMetadata();
258
+ }
259
+ /**
260
+ * Render the SP metadata XML for a specific group connection, deriving SP
261
+ * options from its stored config via {@link getSamlServiceProviderOptions}.
262
+ * @internal
263
+ */
264
+ function createGroupConnectionSamlMetadataXml(opts) {
265
+ return createServiceProviderMetadata(getSamlServiceProviderOptions({
266
+ rootUrl: opts.rootUrl,
267
+ source: opts.source,
268
+ config: opts.config
269
+ }));
270
+ }
271
+ /**
272
+ * Resolve effective SP options for a group connection, layering caller
273
+ * `overrides` over stored `serviceProvider` config over the default group
274
+ * SAML URLs.
275
+ * @internal
276
+ */
277
+ function getSamlServiceProviderOptions(opts) {
278
+ const saml = getSamlConfig(opts.config);
279
+ const sp = asRecord(saml.serviceProvider) ?? {};
280
+ const clockSkewMs = ((asRecord(saml.security) ?? {}).clockSkewSeconds ?? 300) * 1e3;
281
+ const urls = getGroupSamlUrls({
282
+ rootUrl: opts.rootUrl,
283
+ source: opts.source
284
+ });
285
+ return {
286
+ entityId: opts.overrides?.entityId ?? sp.entityId ?? urls.metadataUrl,
287
+ acsUrl: opts.overrides?.acsUrl ?? sp.acsUrl ?? urls.acsUrl,
288
+ sloUrl: opts.overrides?.sloUrl ?? sp.sloUrl ?? urls.sloUrl,
289
+ relayState: opts.relayState,
290
+ authnRequestsSigned: saml.request?.signAuthnRequests,
291
+ signingCert: sp.signingCert,
292
+ encryptCert: sp.encryptCert,
293
+ privateKey: sp.privateKey,
294
+ privateKeyPass: sp.privateKeyPass,
295
+ encPrivateKey: sp.encPrivateKey,
296
+ encPrivateKeyPass: sp.encPrivateKeyPass,
297
+ clockDrifts: [-clockSkewMs, clockSkewMs]
298
+ };
299
+ }
300
+ /**
301
+ * Construct a samlify ServiceProvider from resolved SP options (entityID,
302
+ * ACS/SLO endpoints, signing config).
303
+ * @internal
304
+ */
305
+ function createSamlServiceProvider(opts) {
306
+ const binding = BINDING_URI;
307
+ return createServiceProvider({
308
+ entityID: opts.entityId,
309
+ relayState: opts.relayState ?? "",
310
+ authnRequestsSigned: opts.authnRequestsSigned ?? false,
311
+ privateKey: opts.privateKey,
312
+ privateKeyPass: opts.privateKeyPass,
313
+ signingCert: opts.signingCert,
314
+ encryptCert: opts.encryptCert,
315
+ encPrivateKey: opts.encPrivateKey,
316
+ encPrivateKeyPass: opts.encPrivateKeyPass,
317
+ clockDrifts: opts.clockDrifts,
318
+ assertionConsumerService: [{
319
+ Binding: binding.post,
320
+ Location: opts.acsUrl
321
+ }],
322
+ singleLogoutService: opts.sloUrl ? [{
323
+ Binding: binding.redirect,
324
+ Location: opts.sloUrl
325
+ }, {
326
+ Binding: binding.post,
327
+ Location: opts.sloUrl
328
+ }] : void 0
329
+ });
330
+ }
331
+ /**
332
+ * Build the per-request SAML runtime (SP, IdP, and group URLs) for a group
333
+ * connection. Throws if the connection has no stored IdP metadata XML.
334
+ * @internal
335
+ */
336
+ function createGroupConnectionSamlRuntime(opts) {
337
+ const saml = getSamlConfig(opts.config);
338
+ const spOptions = getSamlServiceProviderOptions({
339
+ rootUrl: opts.rootUrl,
340
+ source: opts.source,
341
+ config: opts.config,
342
+ relayState: opts.relayState,
343
+ overrides: opts.overrides
344
+ });
345
+ if (typeof saml.idp?.metadataXml !== "string") throw new Error("SAML IdP metadata is missing.");
346
+ return {
347
+ saml,
348
+ sp: createSamlServiceProvider(spOptions),
349
+ idp: createIdentityProvider({ metadata: saml.idp.metadataXml }),
350
+ urls: getGroupSamlUrls({
351
+ rootUrl: opts.rootUrl,
352
+ source: opts.source
353
+ })
354
+ };
355
+ }
356
+ function verifySamlTimeWindow(notBefore, notOnOrAfter, clockSkewSeconds) {
357
+ const now = Date.now();
358
+ const drift = clockSkewSeconds * 1e3;
359
+ if (notBefore) {
360
+ const notBeforeTime = new Date(notBefore).getTime();
361
+ if (!Number.isFinite(notBeforeTime)) throw new Error("SAML assertion has an invalid NotBefore timestamp.");
362
+ if (now < notBeforeTime - drift) throw new Error("SAML assertion is not yet valid.");
363
+ }
364
+ if (notOnOrAfter) {
365
+ const notOnOrAfterTime = new Date(notOnOrAfter).getTime();
366
+ if (!Number.isFinite(notOnOrAfterTime)) throw new Error("SAML assertion has an invalid NotOnOrAfter timestamp.");
367
+ if (now >= notOnOrAfterTime + drift) throw new Error("SAML assertion has expired.");
368
+ }
369
+ }
370
+ function normalizeSamlUrl(value) {
371
+ return value.trim().replace(/\/$/, "");
372
+ }
373
+ function toStringArray(value) {
374
+ if (Array.isArray(value)) return value;
375
+ if (typeof value === "string") return [value];
376
+ return [];
377
+ }
378
+ function localName(node) {
379
+ return typeof node === "object" && node !== null ? node.localName ?? node.nodeName : void 0;
380
+ }
381
+ function isElementNode(node) {
382
+ return localName(node) !== void 0;
383
+ }
384
+ function elementChildren(node) {
385
+ const childNodes = typeof node === "object" && node !== null ? node.childNodes : void 0;
386
+ return childNodes ? Array.from(childNodes).filter(isElementNode) : [];
387
+ }
388
+ function findDirectChild(node, name) {
389
+ return elementChildren(node).find((child) => localName(child) === name);
390
+ }
391
+ function findDescendant(node, name) {
392
+ for (const child of elementChildren(node)) {
393
+ if (localName(child) === name) return child;
394
+ const nested = findDescendant(child, name);
395
+ if (nested) return nested;
396
+ }
397
+ }
398
+ function getAttribute(node, name) {
399
+ if (typeof node !== "object" || node === null) return;
400
+ const value = node.getAttribute?.call(node, name);
401
+ return typeof value === "string" ? value : void 0;
402
+ }
403
+ function signatureMetadataFromNode(signatureNode) {
404
+ if (!signatureNode) return;
405
+ const signatureMethod = findDescendant(signatureNode, "SignatureMethod");
406
+ const digestMethod = findDescendant(signatureNode, "DigestMethod");
407
+ return {
408
+ signatureAlgorithm: getAttribute(signatureMethod, "Algorithm"),
409
+ digestAlgorithm: getAttribute(digestMethod, "Algorithm")
410
+ };
411
+ }
412
+ function extractSignatureMetadataFromXml(content) {
413
+ try {
414
+ const root = safeParseXml(content, "text/xml").documentElement;
415
+ if (localName(root) === "Signature") return { responseSignature: signatureMetadataFromNode(root) };
416
+ const responseSignature = signatureMetadataFromNode(findDirectChild(root, "Signature"));
417
+ const assertion = localName(root) === "Assertion" ? root : findDirectChild(root, "Assertion");
418
+ return {
419
+ responseSignature,
420
+ assertionSignature: localName(root) === "Assertion" ? signatureMetadataFromNode(findDirectChild(root, "Signature")) : signatureMetadataFromNode(findDirectChild(assertion, "Signature"))
421
+ };
422
+ } catch {
423
+ return {};
424
+ }
425
+ }
426
+ /**
427
+ * Read the `Assertion/@ID` from cryptographically-verified SAML content,
428
+ * whether the content is the assertion element itself or a response wrapping
429
+ * one. Returns `undefined` when no assertion ID can be resolved (in which case
430
+ * the caller must fail closed rather than treat the response as unique).
431
+ */
432
+ function assertionIdFromXml(content) {
433
+ try {
434
+ const root = safeParseXml(content, "text/xml").documentElement;
435
+ const id = getAttribute(localName(root) === "Assertion" ? root : findDirectChild(root, "Assertion"), "ID");
436
+ return typeof id === "string" && id.length > 0 ? id : void 0;
437
+ } catch {
438
+ return;
439
+ }
440
+ }
441
+ /**
442
+ * Derive the identifiers a SAML ACS handler needs to prevent replay from a
443
+ * parsed login response: the assertion's `ID` (verified from the canonical
444
+ * bytes), the `InResponseTo` binding the response to a pending AuthnRequest,
445
+ * and the tightest `NotOnOrAfter` upper bound (from `<SubjectConfirmationData>`
446
+ * or `<Conditions>`) used to bound the seen-assertion cache's TTL.
447
+ * @internal
448
+ */
449
+ function samlReplayIdentifiers(parsed) {
450
+ const extract = parsed.extract;
451
+ const notOnOrAfter = extract?.subjectConfirmation?.notOnOrAfter ?? extract?.conditions?.notOnOrAfter ?? void 0;
452
+ return {
453
+ assertionId: assertionIdFromXml(parsed.samlContent),
454
+ inResponseTo: extract?.subjectConfirmation?.inResponseTo ?? extract?.response?.inResponseTo,
455
+ notOnOrAfter
456
+ };
457
+ }
458
+ function normalizeSignatureMetadata(value) {
459
+ if (typeof value === "object" && value !== null) {
460
+ const signatureAlgorithm = value.signatureAlgorithm;
461
+ const digestAlgorithm = value.digestAlgorithm;
462
+ if (typeof signatureAlgorithm === "string" || typeof digestAlgorithm === "string") return {
463
+ signatureAlgorithm: typeof signatureAlgorithm === "string" ? signatureAlgorithm : void 0,
464
+ digestAlgorithm: typeof digestAlgorithm === "string" ? digestAlgorithm : void 0
465
+ };
466
+ }
467
+ if (typeof value === "string") return extractSignatureMetadataFromXml(value).responseSignature;
468
+ }
469
+ function attachSamlSignatureMetadata(parsed) {
470
+ const fromXml = extractSignatureMetadataFromXml(parsed.samlContent);
471
+ const responseSignature = normalizeSignatureMetadata(parsed.extract?.signature) ?? fromXml.responseSignature;
472
+ const assertionSignature = normalizeSignatureMetadata(parsed.extract?.assertionSignature) ?? fromXml.assertionSignature;
473
+ return {
474
+ ...parsed,
475
+ extract: {
476
+ ...parsed.extract,
477
+ signature: responseSignature,
478
+ assertionSignature
479
+ }
480
+ };
481
+ }
482
+ function signatureMetadataList(extract) {
483
+ return [normalizeSignatureMetadata(extract?.signature), normalizeSignatureMetadata(extract?.assertionSignature)].filter((metadata) => metadata !== void 0);
484
+ }
485
+ function validateSamlRequiredSignature(extract, security) {
486
+ if (security.requireSignedAssertions === true && typeof normalizeSignatureMetadata(extract?.assertionSignature)?.signatureAlgorithm !== "string") throw new Error("SAML assertion must be signed.");
487
+ }
488
+ function validateSamlRequiredTimestamps(extract, security) {
489
+ if (security.requireTimestamps === false) return;
490
+ if (!(Boolean(extract?.conditions?.notOnOrAfter) || Boolean(extract?.subjectConfirmation?.notOnOrAfter))) throw new Error("SAML assertion is missing a validity window (NotOnOrAfter).");
491
+ }
492
+ function validateSamlTimeWindow(extract, security) {
493
+ const skew = security.clockSkewSeconds ?? 300;
494
+ const conditions = extract?.conditions;
495
+ if (conditions?.notBefore || conditions?.notOnOrAfter) verifySamlTimeWindow(conditions.notBefore, conditions.notOnOrAfter, skew);
496
+ const subjectNotOnOrAfter = extract?.subjectConfirmation?.notOnOrAfter;
497
+ if (subjectNotOnOrAfter) verifySamlTimeWindow(void 0, subjectNotOnOrAfter, skew);
498
+ }
499
+ function validateSamlAudience(extract, expectedAudience) {
500
+ if (expectedAudience !== void 0) {
501
+ if (!toStringArray(extract?.audience).includes(expectedAudience)) throw new Error("SAML assertion audience does not match this service provider.");
502
+ }
503
+ }
504
+ function validateSamlRecipient(extract, expectedAcsUrl) {
505
+ if (expectedAcsUrl !== void 0) {
506
+ const normalizedAcsUrl = normalizeSamlUrl(expectedAcsUrl);
507
+ const recipient = extract?.subjectConfirmation?.recipient;
508
+ if (typeof recipient !== "string" || normalizeSamlUrl(recipient) !== normalizedAcsUrl) throw new Error("SAML assertion recipient does not match this ACS URL.");
509
+ const destination = extract?.response?.destination;
510
+ if (typeof destination === "string" && normalizeSamlUrl(destination) !== normalizedAcsUrl) throw new Error("SAML response destination does not match this ACS URL.");
511
+ }
512
+ }
513
+ /**
514
+ * Enforce the connection's SAML security policy on a parsed assertion:
515
+ * weak-algorithm rejection, required assertion signature, required timestamp
516
+ * conditions, the NotBefore/NotOnOrAfter validity window (with clock skew),
517
+ * the expected audience, and recipient/destination matching the SP's ACS URL.
518
+ * Throws on the first violation.
519
+ * @internal
520
+ */
521
+ function enforceGroupConnectionSamlSecurity(opts) {
522
+ enforceSamlAlgorithmPolicy(opts);
523
+ const security = asRecord(getSamlConfig(opts.config).security) ?? {};
524
+ validateSamlRequiredSignature(opts.extract, security);
525
+ validateSamlRequiredTimestamps(opts.extract, security);
526
+ validateSamlTimeWindow(opts.extract, security);
527
+ validateSamlAudience(opts.extract, opts.expectedAudience);
528
+ validateSamlRecipient(opts.extract, opts.expectedAcsUrl);
529
+ }
530
+ /**
531
+ * Reconstruct the HTTP-Redirect binding's signed octet string from the raw query
532
+ * string, in the SAML-mandated order (`SAMLRequest`|`SAMLResponse`, then
533
+ * `RelayState` if present, then `SigAlg`), preserving each value's exact
534
+ * URL-encoded bytes — re-encoding decoded values would not reproduce what the IdP
535
+ * signed. Returns `undefined` when no SAML message parameter is present, in which
536
+ * case message-signature verification stays fail-closed.
537
+ * @internal
538
+ */
539
+ function reconstructRedirectOctetString(url) {
540
+ const raw = url.search.replace(/^\?/, "");
541
+ const encoded = /* @__PURE__ */ new Map();
542
+ for (const pair of raw.split("&")) {
543
+ if (pair.length === 0) continue;
544
+ const eq = pair.indexOf("=");
545
+ const key = eq === -1 ? pair : pair.slice(0, eq);
546
+ if (!encoded.has(key)) encoded.set(key, eq === -1 ? "" : pair.slice(eq + 1));
547
+ }
548
+ const message = encoded.has("SAMLRequest") ? `SAMLRequest=${encoded.get("SAMLRequest")}` : encoded.has("SAMLResponse") ? `SAMLResponse=${encoded.get("SAMLResponse")}` : void 0;
549
+ if (message === void 0) return;
550
+ const parts = [message];
551
+ if (encoded.has("RelayState")) parts.push(`RelayState=${encoded.get("RelayState")}`);
552
+ if (encoded.has("SigAlg")) parts.push(`SigAlg=${encoded.get("SigAlg")}`);
553
+ return parts.join("&");
554
+ }
555
+ function toSamlHttpRequest(request) {
556
+ return {
557
+ query: request.query,
558
+ body: request.body,
559
+ ...request.binding === "redirect" ? { octetString: reconstructRedirectOctetString(request.url) } : {}
560
+ };
561
+ }
562
+ /**
563
+ * Create the IdP-bound SAML AuthnRequest for a group connection, returning the
564
+ * binding plus either a redirect URL (HTTP-Redirect) or POST endpoint/value
565
+ * (HTTP-POST), along with the encoded RelayState carrying the signed flow
566
+ * state and request id.
567
+ * @internal
568
+ */
569
+ async function createGroupConnectionSamlSignInRequest(opts) {
570
+ const runtime = createGroupConnectionSamlRuntime({
571
+ rootUrl: opts.rootUrl,
572
+ source: opts.source,
573
+ config: opts.config
574
+ });
575
+ const binding = runtime.saml.idp?.connection?.redirect ? "redirect" : "post";
576
+ const loginRequest = await runtime.sp.createLoginRequest(runtime.idp, binding);
577
+ const relayState = encodeGroupSamlRelayState({
578
+ source: opts.source,
579
+ signature: opts.signature,
580
+ requestId: loginRequest.id,
581
+ state: opts.state,
582
+ redirectTo: opts.redirectTo
583
+ });
584
+ return {
585
+ requestId: loginRequest.id,
586
+ binding,
587
+ relayState,
588
+ redirectUrl: binding === "redirect" ? (() => {
589
+ const redirectUrl = new URL(loginRequest.context);
590
+ redirectUrl.searchParams.set("RelayState", relayState);
591
+ return redirectUrl.toString();
592
+ })() : void 0,
593
+ post: binding === "post" ? {
594
+ endpoint: loginRequest.entityEndpoint,
595
+ value: loginRequest.context
596
+ } : void 0
597
+ };
598
+ }
599
+ /**
600
+ * Parse and partially validate a SAML login Response for a group connection:
601
+ * enforces the response size limit, builds the runtime, parses the response,
602
+ * attaches signature metadata, warns on weak algorithms, and decodes the
603
+ * RelayState. Does not itself enforce the full security policy — callers must
604
+ * also run {@link enforceGroupConnectionSamlSecurity}.
605
+ * @internal
606
+ */
607
+ async function parseGroupConnectionSamlLoginResponse(opts) {
608
+ ensureSamlifyValidator();
609
+ const httpRequest = await readGroupConnectionSamlHttpRequest(opts.request);
610
+ enforceSamlResponseSize({
611
+ request: httpRequest,
612
+ config: opts.config
613
+ });
614
+ const runtime = createGroupConnectionSamlRuntime({
615
+ rootUrl: opts.rootUrl,
616
+ source: opts.source,
617
+ config: opts.config
618
+ });
619
+ const parsed = attachSamlSignatureMetadata(await runtime.sp.parseLoginResponse(runtime.idp, httpRequest.binding, toSamlHttpRequest(httpRequest)));
620
+ warnWeakSamlAlgorithms(parsed);
621
+ return {
622
+ ...httpRequest,
623
+ runtime,
624
+ parsed,
625
+ relayState: decodeGroupSamlRelayStateOrThrow(httpRequest.relayState ?? null)
626
+ };
627
+ }
628
+ const WEAK_SAML_ALGORITHMS = new Set([
629
+ "http://www.w3.org/2000/09/xmldsig#rsa-sha1",
630
+ "http://www.w3.org/2000/09/xmldsig#dsa-sha1",
631
+ "http://www.w3.org/2000/09/xmldsig#sha1",
632
+ "http://www.w3.org/2001/04/xmlenc#rsa-1_5",
633
+ "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"
634
+ ]);
635
+ /**
636
+ * Warn when the SAML response uses weak cryptographic algorithms
637
+ * such as SHA-1, RSA 1.5, or 3DES. Algorithm-check failures are non-critical
638
+ * and swallowed so they never break the auth flow.
639
+ */
640
+ function warnWeakSamlAlgorithms(parsed) {
641
+ try {
642
+ for (const metadata of signatureMetadataList(parsed.extract)) {
643
+ const sigAlg = metadata.signatureAlgorithm;
644
+ const digestAlg = metadata.digestAlgorithm;
645
+ if (sigAlg && WEAK_SAML_ALGORITHMS.has(sigAlg)) log("WARN", `[convex-auth] SAML response uses weak signature algorithm: ${sigAlg}. Consider upgrading your IdP to use RSA-SHA256 or stronger.`);
646
+ if (digestAlg && WEAK_SAML_ALGORITHMS.has(digestAlg)) log("WARN", `[convex-auth] SAML response uses weak digest algorithm: ${digestAlg}. Consider upgrading your IdP to use SHA-256 or stronger.`);
647
+ }
648
+ } catch {
649
+ return;
650
+ }
651
+ }
652
+ /**
653
+ * Reject a SAML response/assertion whose signature or digest uses a known-weak
654
+ * algorithm (SHA-1, RSA-1.5, 3DES). Secure by default: rejection is the default
655
+ * and operators must explicitly set `security.weakAlgorithmHandling: "warn"` to
656
+ * downgrade to a warning (mirroring the `requireTimestamps` opt-out).
657
+ * @internal
658
+ */
659
+ function enforceSamlAlgorithmPolicy(opts) {
660
+ if (getSamlSecurityConfig(opts.config).weakAlgorithmHandling === "warn") return;
661
+ for (const metadata of signatureMetadataList(opts.extract)) {
662
+ const sigAlg = metadata.signatureAlgorithm;
663
+ const digestAlg = metadata.digestAlgorithm;
664
+ if (sigAlg && WEAK_SAML_ALGORITHMS.has(sigAlg) || digestAlg && WEAK_SAML_ALGORITHMS.has(digestAlg)) throw new Error("SAML response uses a rejected weak cryptographic algorithm.");
665
+ }
666
+ }
667
+ /**
668
+ * Bind the returned RelayState to the pending login request: throws unless its
669
+ * source matches the connection and its requestId matches the assertion's
670
+ * `InResponseTo`, defeating cross-connection and replayed responses.
671
+ * @internal
672
+ */
673
+ function validateGroupConnectionSamlLoginRelayState(opts) {
674
+ if (opts.relayState.source.kind !== opts.source.kind || opts.relayState.source.id !== opts.source.id || opts.relayState.requestId !== opts.inResponseTo) throw new Error("SAML RelayState did not match the pending login request.");
675
+ }
676
+ /**
677
+ * Parse an inbound SAML single-logout message (request and/or response) for a
678
+ * group connection, returning the parsed flow(s) alongside the runtime.
679
+ *
680
+ * SECURITY — SLO messages are treated as UNAUTHENTICATED. samlify only verifies
681
+ * an inbound `LogoutRequest`/`LogoutResponse` signature when the SP is built
682
+ * with `wantLogoutRequestSigned`/`wantLogoutResponseSigned`; both default to
683
+ * `false` and are intentionally left unset in {@link createSamlServiceProvider}
684
+ * (many IdPs do not sign logout messages, and requiring it would break those
685
+ * legitimate SLO flows). This is safe only because the sole caller,
686
+ * `handleSamlSlo` in the connection HTTP router, DOES NOT terminate any local
687
+ * session: for an inbound `LogoutRequest` it merely emits the protocol
688
+ * `LogoutResponse` acknowledgment, and for an inbound `LogoutResponse` it
689
+ * returns `204` and does nothing. A forged, replayed, or attacker-supplied
690
+ * logout message therefore cannot force-log-out a user.
691
+ *
692
+ * DO NOT wire session termination onto this parse result without FIRST requiring
693
+ * signed logout messages (via the `wantLogout*Signed` SP options above) and
694
+ * rejecting unsigned ones — otherwise an unauthenticated caller could trigger a
695
+ * logout-CSRF / denial-of-service.
696
+ * @internal
697
+ */
698
+ async function parseGroupConnectionSamlLogoutMessage(opts) {
699
+ ensureSamlifyValidator();
700
+ const httpRequest = await readGroupConnectionSamlHttpRequest(opts.request);
701
+ const runtime = createGroupConnectionSamlRuntime({
702
+ rootUrl: opts.rootUrl,
703
+ source: opts.source,
704
+ config: opts.config,
705
+ relayState: httpRequest.relayState
706
+ });
707
+ const parsedRequest = httpRequest.hasSamlRequest ? await runtime.sp.parseLogoutRequest(runtime.idp, httpRequest.binding, toSamlHttpRequest(httpRequest)) : void 0;
708
+ const parsedResponse = httpRequest.hasSamlResponse ? await runtime.sp.parseLogoutResponse(runtime.idp, httpRequest.binding, toSamlHttpRequest(httpRequest)) : void 0;
709
+ return {
710
+ ...httpRequest,
711
+ runtime,
712
+ parsedRequest,
713
+ parsedResponse
714
+ };
715
+ }
716
+ /**
717
+ * Map a parsed SAML assertion's attributes (via the connection's attribute
718
+ * mapping, falling back to NameID for the subject) into a normalized profile.
719
+ * Throws if no subject can be resolved.
720
+ *
721
+ * @remarks
722
+ * `emailVerified` is always left `undefined`: SAML carries no `email_verified`
723
+ * claim, so the assertion alone never proves the email. Verification is decided
724
+ * downstream (`userOAuthImpl`) from whether the email's domain is a verified
725
+ * connection domain, keeping a SAML-asserted email unverified by default so it
726
+ * cannot drive cross-connection `verifiedEmail` account linking.
727
+ * @internal
728
+ */
729
+ function profileFromSamlExtract(extract, mapping) {
730
+ const attributes = typeof extract?.attributes === "object" && extract.attributes !== null ? extract.attributes : {};
731
+ const resolveFirst = (...keys) => {
732
+ for (const key of keys) {
733
+ if (!key) continue;
734
+ const attribute = attributes[key];
735
+ const value = Array.isArray(attribute) ? attribute[0] : attribute;
736
+ if (value !== void 0) return value;
737
+ }
738
+ };
739
+ const fieldResolvers = {
740
+ email: () => resolveFirst(mapping?.email),
741
+ groups: () => normalizeStringArray(resolveFirst(mapping?.groups)),
742
+ name: () => resolveFirst(mapping?.name) ?? ([resolveFirst(mapping?.firstName), resolveFirst(mapping?.lastName)].filter(Boolean).join(" ") || void 0),
743
+ roles: () => normalizeStringArray(resolveFirst(mapping?.roles)),
744
+ subject: () => resolveFirst(mapping?.subject) ?? extract?.nameID
745
+ };
746
+ const subject = fieldResolvers.subject();
747
+ if (subject === void 0) throw new Error("SAML profile is missing a subject. Configure `attributeMapping.subject` or ensure the assertion includes a NameID.");
748
+ return finalizeNormalizedProfile({
749
+ id: subject,
750
+ email: fieldResolvers.email(),
751
+ emailVerified: void 0,
752
+ groups: fieldResolvers.groups(),
753
+ name: fieldResolvers.name(),
754
+ roles: fieldResolvers.roles(),
755
+ samlAttributes: attributes,
756
+ samlSessionIndex: extract?.sessionIndex?.sessionIndex
757
+ });
758
+ }
759
+
760
+ //#endregion
761
+ export { createGroupConnectionSamlMetadataXml, createGroupConnectionSamlSignInRequest, createSamlPostBindingResponse, createServiceProviderMetadata, encodeGroupSamlRelayState, enforceGroupConnectionSamlSecurity, getSamlServiceProviderOptions, parseGroupConnectionSamlLoginResponse, parseGroupConnectionSamlLogoutMessage, parseSamlIdpMetadataChecked, profileFromSamlExtract, samlReplayIdentifiers, validateGroupConnectionSamlLoginRelayState };
762
+ //# sourceMappingURL=saml.js.map