@oxy.so/core 1.0.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.
- package/LICENSE +202 -0
- package/NOTICE +16 -0
- package/README.md +221 -0
- package/dist/cjs/.tsbuildinfo +1 -0
- package/dist/cjs/HttpService.js +1270 -0
- package/dist/cjs/OxyServices.base.js +390 -0
- package/dist/cjs/OxyServices.errors.js +95 -0
- package/dist/cjs/OxyServices.js +72 -0
- package/dist/cjs/boot/sessionColdBoot.js +395 -0
- package/dist/cjs/constants/version.js +16 -0
- package/dist/cjs/crypto/aead.js +79 -0
- package/dist/cjs/crypto/ecdh.js +35 -0
- package/dist/cjs/crypto/identityMarker.js +255 -0
- package/dist/cjs/crypto/kdf.js +39 -0
- package/dist/cjs/crypto/keyManager.js +2234 -0
- package/dist/cjs/crypto/polyfill.js +131 -0
- package/dist/cjs/crypto/recoveryPhrase.js +242 -0
- package/dist/cjs/crypto/signatureService.js +273 -0
- package/dist/cjs/i18n/accountCategoryLabels.js +44 -0
- package/dist/cjs/i18n/accountRoleLabels.js +27 -0
- package/dist/cjs/i18n/index.js +90 -0
- package/dist/cjs/i18n/locales/ar-SA.json +282 -0
- package/dist/cjs/i18n/locales/ca-ES.json +282 -0
- package/dist/cjs/i18n/locales/de-DE.json +282 -0
- package/dist/cjs/i18n/locales/en-US.json +2161 -0
- package/dist/cjs/i18n/locales/es-ES.json +2161 -0
- package/dist/cjs/i18n/locales/fr-FR.json +282 -0
- package/dist/cjs/i18n/locales/it-IT.json +282 -0
- package/dist/cjs/i18n/locales/ja-JP.json +282 -0
- package/dist/cjs/i18n/locales/ko-KR.json +282 -0
- package/dist/cjs/i18n/locales/locales/ar-SA.json +282 -0
- package/dist/cjs/i18n/locales/locales/ca-ES.json +282 -0
- package/dist/cjs/i18n/locales/locales/de-DE.json +282 -0
- package/dist/cjs/i18n/locales/locales/en-US.json +2161 -0
- package/dist/cjs/i18n/locales/locales/es-ES.json +2161 -0
- package/dist/cjs/i18n/locales/locales/fr-FR.json +282 -0
- package/dist/cjs/i18n/locales/locales/it-IT.json +282 -0
- package/dist/cjs/i18n/locales/locales/ja-JP.json +282 -0
- package/dist/cjs/i18n/locales/locales/ko-KR.json +282 -0
- package/dist/cjs/i18n/locales/locales/pt-PT.json +282 -0
- package/dist/cjs/i18n/locales/locales/zh-CN.json +282 -0
- package/dist/cjs/i18n/locales/pt-PT.json +282 -0
- package/dist/cjs/i18n/locales/zh-CN.json +282 -0
- package/dist/cjs/i18n/reputationCategoryLabels.js +20 -0
- package/dist/cjs/i18n/trustTierLabels.js +19 -0
- package/dist/cjs/index.js +498 -0
- package/dist/cjs/inference/OxyInferenceClient.js +544 -0
- package/dist/cjs/logger/index.js +149 -0
- package/dist/cjs/mixins/OxyServices.accounts.js +555 -0
- package/dist/cjs/mixins/OxyServices.analytics.js +49 -0
- package/dist/cjs/mixins/OxyServices.appData.js +108 -0
- package/dist/cjs/mixins/OxyServices.assets.js +764 -0
- package/dist/cjs/mixins/OxyServices.auth.js +1254 -0
- package/dist/cjs/mixins/OxyServices.chains.js +73 -0
- package/dist/cjs/mixins/OxyServices.civic.js +611 -0
- package/dist/cjs/mixins/OxyServices.connectedApps.js +78 -0
- package/dist/cjs/mixins/OxyServices.contacts.js +50 -0
- package/dist/cjs/mixins/OxyServices.deviceBoot.js +191 -0
- package/dist/cjs/mixins/OxyServices.deviceTransfer.js +314 -0
- package/dist/cjs/mixins/OxyServices.devices.js +116 -0
- package/dist/cjs/mixins/OxyServices.features.js +335 -0
- package/dist/cjs/mixins/OxyServices.followGraph.js +221 -0
- package/dist/cjs/mixins/OxyServices.identity.js +461 -0
- package/dist/cjs/mixins/OxyServices.identityBackup.js +172 -0
- package/dist/cjs/mixins/OxyServices.inference.js +59 -0
- package/dist/cjs/mixins/OxyServices.language.js +125 -0
- package/dist/cjs/mixins/OxyServices.links.js +72 -0
- package/dist/cjs/mixins/OxyServices.location.js +43 -0
- package/dist/cjs/mixins/OxyServices.nodes.js +175 -0
- package/dist/cjs/mixins/OxyServices.notifications.js +63 -0
- package/dist/cjs/mixins/OxyServices.payment.js +158 -0
- package/dist/cjs/mixins/OxyServices.privacy.js +199 -0
- package/dist/cjs/mixins/OxyServices.reputation.js +289 -0
- package/dist/cjs/mixins/OxyServices.security.js +89 -0
- package/dist/cjs/mixins/OxyServices.store.js +266 -0
- package/dist/cjs/mixins/OxyServices.topics.js +137 -0
- package/dist/cjs/mixins/OxyServices.user.js +902 -0
- package/dist/cjs/mixins/OxyServices.utility.js +1098 -0
- package/dist/cjs/mixins/index.js +135 -0
- package/dist/cjs/mixins/mixinHelpers.js +53 -0
- package/dist/cjs/models/Topic.js +16 -0
- package/dist/cjs/models/interfaces.js +20 -0
- package/dist/cjs/models/session.js +2 -0
- package/dist/cjs/server/auth.js +167 -0
- package/dist/cjs/server/capabilityTicket.js +192 -0
- package/dist/cjs/server/cors.js +225 -0
- package/dist/cjs/server/index.js +97 -0
- package/dist/cjs/server/rateLimit.js +207 -0
- package/dist/cjs/server/safeFetch.js +458 -0
- package/dist/cjs/server/securityHeaders.js +377 -0
- package/dist/cjs/server/userInvalidation.js +156 -0
- package/dist/cjs/server/verifySecret.js +50 -0
- package/dist/cjs/session/SessionClient.js +865 -0
- package/dist/cjs/session/accountDelegationAccess.js +48 -0
- package/dist/cjs/session/accountDialogController.js +1131 -0
- package/dist/cjs/session/accountSwitchTargets.js +81 -0
- package/dist/cjs/session/authStateStore.js +404 -0
- package/dist/cjs/session/createSessionClient.js +32 -0
- package/dist/cjs/session/deviceDirectory.js +143 -0
- package/dist/cjs/session/deviceSwitcherRows.js +76 -0
- package/dist/cjs/session/identityPin.js +256 -0
- package/dist/cjs/session/identitySession.js +135 -0
- package/dist/cjs/session/projectSessionState.js +121 -0
- package/dist/cjs/session/refresh.js +398 -0
- package/dist/cjs/session/sessionClientHost.js +34 -0
- package/dist/cjs/session/sharedDeviceCredential.js +247 -0
- package/dist/cjs/session/socketLoader.js +55 -0
- package/dist/cjs/shared/utils/colorUtils.js +153 -0
- package/dist/cjs/shared/utils/errorUtils.js +183 -0
- package/dist/cjs/shared/utils/index.js +49 -0
- package/dist/cjs/shared/utils/networkUtils.js +183 -0
- package/dist/cjs/shared/utils/themeUtils.js +106 -0
- package/dist/cjs/utils/accountCacheSweep.js +80 -0
- package/dist/cjs/utils/accountUtils.js +140 -0
- package/dist/cjs/utils/activityId.js +6 -0
- package/dist/cjs/utils/apiUtils.js +91 -0
- package/dist/cjs/utils/asyncUtils.js +222 -0
- package/dist/cjs/utils/authHelpers.js +120 -0
- package/dist/cjs/utils/authWebUrl.js +19 -0
- package/dist/cjs/utils/avatarUtils.js +29 -0
- package/dist/cjs/utils/cache.js +235 -0
- package/dist/cjs/utils/cacheKey.js +85 -0
- package/dist/cjs/utils/coldBoot.js +122 -0
- package/dist/cjs/utils/commonsApproval.js +31 -0
- package/dist/cjs/utils/commonsDelivery.js +59 -0
- package/dist/cjs/utils/deviceManager.js +174 -0
- package/dist/cjs/utils/displayNamePolicyRanges.generated.js +60 -0
- package/dist/cjs/utils/edgeRegion.js +6 -0
- package/dist/cjs/utils/errorUtils.js +243 -0
- package/dist/cjs/utils/identityCacheSweep.js +97 -0
- package/dist/cjs/utils/languageUtils.js +224 -0
- package/dist/cjs/utils/oauthPkce.js +311 -0
- package/dist/cjs/utils/officialOrigins.js +64 -0
- package/dist/cjs/utils/oxyServiceEnvironment.js +19 -0
- package/dist/cjs/utils/platform.js +119 -0
- package/dist/cjs/utils/profileLinks.js +63 -0
- package/dist/cjs/utils/redactUrl.js +29 -0
- package/dist/cjs/utils/registrableApex.js +45 -0
- package/dist/cjs/utils/requestUtils.js +209 -0
- package/dist/cjs/utils/sessionUtils.js +181 -0
- package/dist/cjs/utils/textNormalization.js +158 -0
- package/dist/cjs/utils/userHandle.js +37 -0
- package/dist/cjs/utils/userIdentity.js +50 -0
- package/dist/cjs/utils/validationUtils.js +370 -0
- package/dist/cjs/utils/webauthnOrigin.js +51 -0
- package/dist/esm/.tsbuildinfo +1 -0
- package/dist/esm/HttpService.js +1266 -0
- package/dist/esm/OxyServices.base.js +386 -0
- package/dist/esm/OxyServices.errors.js +88 -0
- package/dist/esm/OxyServices.js +66 -0
- package/dist/esm/boot/sessionColdBoot.js +392 -0
- package/dist/esm/constants/version.js +13 -0
- package/dist/esm/crypto/aead.js +74 -0
- package/dist/esm/crypto/ecdh.js +32 -0
- package/dist/esm/crypto/identityMarker.js +248 -0
- package/dist/esm/crypto/kdf.js +36 -0
- package/dist/esm/crypto/keyManager.js +2227 -0
- package/dist/esm/crypto/polyfill.js +129 -0
- package/dist/esm/crypto/recoveryPhrase.js +238 -0
- package/dist/esm/crypto/signatureService.js +269 -0
- package/dist/esm/i18n/accountCategoryLabels.js +37 -0
- package/dist/esm/i18n/accountRoleLabels.js +20 -0
- package/dist/esm/i18n/index.js +83 -0
- package/dist/esm/i18n/locales/ar-SA.json +282 -0
- package/dist/esm/i18n/locales/ca-ES.json +282 -0
- package/dist/esm/i18n/locales/de-DE.json +282 -0
- package/dist/esm/i18n/locales/en-US.json +2161 -0
- package/dist/esm/i18n/locales/es-ES.json +2161 -0
- package/dist/esm/i18n/locales/fr-FR.json +282 -0
- package/dist/esm/i18n/locales/it-IT.json +282 -0
- package/dist/esm/i18n/locales/ja-JP.json +282 -0
- package/dist/esm/i18n/locales/ko-KR.json +282 -0
- package/dist/esm/i18n/locales/locales/ar-SA.json +282 -0
- package/dist/esm/i18n/locales/locales/ca-ES.json +282 -0
- package/dist/esm/i18n/locales/locales/de-DE.json +282 -0
- package/dist/esm/i18n/locales/locales/en-US.json +2161 -0
- package/dist/esm/i18n/locales/locales/es-ES.json +2161 -0
- package/dist/esm/i18n/locales/locales/fr-FR.json +282 -0
- package/dist/esm/i18n/locales/locales/it-IT.json +282 -0
- package/dist/esm/i18n/locales/locales/ja-JP.json +282 -0
- package/dist/esm/i18n/locales/locales/ko-KR.json +282 -0
- package/dist/esm/i18n/locales/locales/pt-PT.json +282 -0
- package/dist/esm/i18n/locales/locales/zh-CN.json +282 -0
- package/dist/esm/i18n/locales/pt-PT.json +282 -0
- package/dist/esm/i18n/locales/zh-CN.json +282 -0
- package/dist/esm/i18n/reputationCategoryLabels.js +13 -0
- package/dist/esm/i18n/trustTierLabels.js +12 -0
- package/dist/esm/index.js +254 -0
- package/dist/esm/inference/OxyInferenceClient.js +538 -0
- package/dist/esm/logger/index.js +140 -0
- package/dist/esm/mixins/OxyServices.accounts.js +543 -0
- package/dist/esm/mixins/OxyServices.analytics.js +46 -0
- package/dist/esm/mixins/OxyServices.appData.js +103 -0
- package/dist/esm/mixins/OxyServices.assets.js +761 -0
- package/dist/esm/mixins/OxyServices.auth.js +1247 -0
- package/dist/esm/mixins/OxyServices.chains.js +70 -0
- package/dist/esm/mixins/OxyServices.civic.js +605 -0
- package/dist/esm/mixins/OxyServices.connectedApps.js +75 -0
- package/dist/esm/mixins/OxyServices.contacts.js +47 -0
- package/dist/esm/mixins/OxyServices.deviceBoot.js +186 -0
- package/dist/esm/mixins/OxyServices.deviceTransfer.js +311 -0
- package/dist/esm/mixins/OxyServices.devices.js +113 -0
- package/dist/esm/mixins/OxyServices.features.js +332 -0
- package/dist/esm/mixins/OxyServices.followGraph.js +218 -0
- package/dist/esm/mixins/OxyServices.identity.js +457 -0
- package/dist/esm/mixins/OxyServices.identityBackup.js +169 -0
- package/dist/esm/mixins/OxyServices.inference.js +56 -0
- package/dist/esm/mixins/OxyServices.language.js +122 -0
- package/dist/esm/mixins/OxyServices.links.js +69 -0
- package/dist/esm/mixins/OxyServices.location.js +40 -0
- package/dist/esm/mixins/OxyServices.nodes.js +172 -0
- package/dist/esm/mixins/OxyServices.notifications.js +60 -0
- package/dist/esm/mixins/OxyServices.payment.js +155 -0
- package/dist/esm/mixins/OxyServices.privacy.js +196 -0
- package/dist/esm/mixins/OxyServices.reputation.js +286 -0
- package/dist/esm/mixins/OxyServices.security.js +86 -0
- package/dist/esm/mixins/OxyServices.store.js +263 -0
- package/dist/esm/mixins/OxyServices.topics.js +134 -0
- package/dist/esm/mixins/OxyServices.user.js +899 -0
- package/dist/esm/mixins/OxyServices.utility.js +1095 -0
- package/dist/esm/mixins/index.js +132 -0
- package/dist/esm/mixins/mixinHelpers.js +48 -0
- package/dist/esm/models/Topic.js +13 -0
- package/dist/esm/models/interfaces.js +17 -0
- package/dist/esm/models/session.js +1 -0
- package/dist/esm/server/auth.js +154 -0
- package/dist/esm/server/capabilityTicket.js +183 -0
- package/dist/esm/server/cors.js +220 -0
- package/dist/esm/server/index.js +47 -0
- package/dist/esm/server/rateLimit.js +201 -0
- package/dist/esm/server/safeFetch.js +447 -0
- package/dist/esm/server/securityHeaders.js +364 -0
- package/dist/esm/server/userInvalidation.js +152 -0
- package/dist/esm/server/verifySecret.js +47 -0
- package/dist/esm/session/SessionClient.js +861 -0
- package/dist/esm/session/accountDelegationAccess.js +45 -0
- package/dist/esm/session/accountDialogController.js +1126 -0
- package/dist/esm/session/accountSwitchTargets.js +77 -0
- package/dist/esm/session/authStateStore.js +398 -0
- package/dist/esm/session/createSessionClient.js +29 -0
- package/dist/esm/session/deviceDirectory.js +135 -0
- package/dist/esm/session/deviceSwitcherRows.js +72 -0
- package/dist/esm/session/identityPin.js +249 -0
- package/dist/esm/session/identitySession.js +131 -0
- package/dist/esm/session/projectSessionState.js +114 -0
- package/dist/esm/session/refresh.js +390 -0
- package/dist/esm/session/sessionClientHost.js +31 -0
- package/dist/esm/session/sharedDeviceCredential.js +239 -0
- package/dist/esm/session/socketLoader.js +19 -0
- package/dist/esm/shared/utils/colorUtils.js +143 -0
- package/dist/esm/shared/utils/errorUtils.js +170 -0
- package/dist/esm/shared/utils/index.js +15 -0
- package/dist/esm/shared/utils/networkUtils.js +173 -0
- package/dist/esm/shared/utils/themeUtils.js +98 -0
- package/dist/esm/utils/accountCacheSweep.js +75 -0
- package/dist/esm/utils/accountUtils.js +131 -0
- package/dist/esm/utils/activityId.js +2 -0
- package/dist/esm/utils/apiUtils.js +84 -0
- package/dist/esm/utils/asyncUtils.js +207 -0
- package/dist/esm/utils/authHelpers.js +111 -0
- package/dist/esm/utils/authWebUrl.js +16 -0
- package/dist/esm/utils/avatarUtils.js +26 -0
- package/dist/esm/utils/cache.js +227 -0
- package/dist/esm/utils/cacheKey.js +80 -0
- package/dist/esm/utils/coldBoot.js +119 -0
- package/dist/esm/utils/commonsApproval.js +27 -0
- package/dist/esm/utils/commonsDelivery.js +54 -0
- package/dist/esm/utils/deviceManager.js +170 -0
- package/dist/esm/utils/displayNamePolicyRanges.generated.js +57 -0
- package/dist/esm/utils/edgeRegion.js +2 -0
- package/dist/esm/utils/errorUtils.js +232 -0
- package/dist/esm/utils/identityCacheSweep.js +92 -0
- package/dist/esm/utils/languageUtils.js +212 -0
- package/dist/esm/utils/oauthPkce.js +297 -0
- package/dist/esm/utils/officialOrigins.js +59 -0
- package/dist/esm/utils/oxyServiceEnvironment.js +16 -0
- package/dist/esm/utils/platform.js +110 -0
- package/dist/esm/utils/profileLinks.js +60 -0
- package/dist/esm/utils/redactUrl.js +26 -0
- package/dist/esm/utils/registrableApex.js +42 -0
- package/dist/esm/utils/requestUtils.js +203 -0
- package/dist/esm/utils/sessionUtils.js +171 -0
- package/dist/esm/utils/textNormalization.js +154 -0
- package/dist/esm/utils/userHandle.js +33 -0
- package/dist/esm/utils/userIdentity.js +45 -0
- package/dist/esm/utils/validationUtils.js +350 -0
- package/dist/esm/utils/webauthnOrigin.js +48 -0
- package/dist/types/.tsbuildinfo +1 -0
- package/dist/types/HttpService.d.ts +413 -0
- package/dist/types/OxyServices.base.d.ts +187 -0
- package/dist/types/OxyServices.d.ts +139 -0
- package/dist/types/OxyServices.errors.d.ts +84 -0
- package/dist/types/boot/sessionColdBoot.d.ts +140 -0
- package/dist/types/constants/version.d.ts +13 -0
- package/dist/types/crypto/aead.d.ts +56 -0
- package/dist/types/crypto/ecdh.d.ts +29 -0
- package/dist/types/crypto/identityMarker.d.ts +94 -0
- package/dist/types/crypto/kdf.d.ts +25 -0
- package/dist/types/crypto/keyManager.d.ts +582 -0
- package/dist/types/crypto/polyfill.d.ts +25 -0
- package/dist/types/crypto/recoveryPhrase.d.ts +173 -0
- package/dist/types/crypto/signatureService.d.ts +136 -0
- package/dist/types/i18n/accountCategoryLabels.d.ts +34 -0
- package/dist/types/i18n/accountRoleLabels.d.ts +10 -0
- package/dist/types/i18n/index.d.ts +3 -0
- package/dist/types/i18n/reputationCategoryLabels.d.ts +10 -0
- package/dist/types/i18n/trustTierLabels.d.ts +9 -0
- package/dist/types/index.d.ts +145 -0
- package/dist/types/inference/OxyInferenceClient.d.ts +342 -0
- package/dist/types/logger/index.d.ts +104 -0
- package/dist/types/mixins/OxyServices.accounts.d.ts +868 -0
- package/dist/types/mixins/OxyServices.analytics.d.ts +72 -0
- package/dist/types/mixins/OxyServices.appData.d.ts +108 -0
- package/dist/types/mixins/OxyServices.assets.d.ts +329 -0
- package/dist/types/mixins/OxyServices.auth.d.ts +908 -0
- package/dist/types/mixins/OxyServices.chains.d.ts +156 -0
- package/dist/types/mixins/OxyServices.civic.d.ts +510 -0
- package/dist/types/mixins/OxyServices.connectedApps.d.ts +169 -0
- package/dist/types/mixins/OxyServices.contacts.d.ts +100 -0
- package/dist/types/mixins/OxyServices.deviceBoot.d.ts +185 -0
- package/dist/types/mixins/OxyServices.deviceTransfer.d.ts +149 -0
- package/dist/types/mixins/OxyServices.devices.d.ts +103 -0
- package/dist/types/mixins/OxyServices.features.d.ts +250 -0
- package/dist/types/mixins/OxyServices.followGraph.d.ts +223 -0
- package/dist/types/mixins/OxyServices.identity.d.ts +351 -0
- package/dist/types/mixins/OxyServices.identityBackup.d.ts +129 -0
- package/dist/types/mixins/OxyServices.inference.d.ts +95 -0
- package/dist/types/mixins/OxyServices.language.d.ts +87 -0
- package/dist/types/mixins/OxyServices.links.d.ts +104 -0
- package/dist/types/mixins/OxyServices.location.d.ts +70 -0
- package/dist/types/mixins/OxyServices.nodes.d.ts +198 -0
- package/dist/types/mixins/OxyServices.notifications.d.ts +143 -0
- package/dist/types/mixins/OxyServices.payment.d.ts +117 -0
- package/dist/types/mixins/OxyServices.privacy.d.ts +146 -0
- package/dist/types/mixins/OxyServices.reputation.d.ts +202 -0
- package/dist/types/mixins/OxyServices.security.d.ts +84 -0
- package/dist/types/mixins/OxyServices.store.d.ts +334 -0
- package/dist/types/mixins/OxyServices.topics.d.ts +110 -0
- package/dist/types/mixins/OxyServices.user.d.ts +558 -0
- package/dist/types/mixins/OxyServices.utility.d.ts +393 -0
- package/dist/types/mixins/index.d.ts +87 -0
- package/dist/types/mixins/mixinHelpers.d.ts +31 -0
- package/dist/types/models/Topic.d.ts +42 -0
- package/dist/types/models/interfaces.d.ts +675 -0
- package/dist/types/models/session.d.ts +51 -0
- package/dist/types/server/auth.d.ts +130 -0
- package/dist/types/server/capabilityTicket.d.ts +41 -0
- package/dist/types/server/cors.d.ts +98 -0
- package/dist/types/server/index.d.ts +35 -0
- package/dist/types/server/rateLimit.d.ts +40 -0
- package/dist/types/server/safeFetch.d.ts +137 -0
- package/dist/types/server/securityHeaders.d.ts +221 -0
- package/dist/types/server/userInvalidation.d.ts +114 -0
- package/dist/types/server/verifySecret.d.ts +29 -0
- package/dist/types/session/SessionClient.d.ts +418 -0
- package/dist/types/session/accountDelegationAccess.d.ts +40 -0
- package/dist/types/session/accountDialogController.d.ts +648 -0
- package/dist/types/session/accountSwitchTargets.d.ts +70 -0
- package/dist/types/session/authStateStore.d.ts +153 -0
- package/dist/types/session/createSessionClient.d.ts +30 -0
- package/dist/types/session/deviceDirectory.d.ts +182 -0
- package/dist/types/session/deviceSwitcherRows.d.ts +92 -0
- package/dist/types/session/identityPin.d.ts +87 -0
- package/dist/types/session/identitySession.d.ts +105 -0
- package/dist/types/session/projectSessionState.d.ts +74 -0
- package/dist/types/session/refresh.d.ts +179 -0
- package/dist/types/session/sessionClientHost.d.ts +18 -0
- package/dist/types/session/sharedDeviceCredential.d.ts +202 -0
- package/dist/types/session/socketLoader.d.ts +11 -0
- package/dist/types/shared/utils/colorUtils.d.ts +104 -0
- package/dist/types/shared/utils/errorUtils.d.ts +97 -0
- package/dist/types/shared/utils/index.d.ts +13 -0
- package/dist/types/shared/utils/networkUtils.d.ts +139 -0
- package/dist/types/shared/utils/themeUtils.d.ts +90 -0
- package/dist/types/utils/accountCacheSweep.d.ts +75 -0
- package/dist/types/utils/accountUtils.d.ts +100 -0
- package/dist/types/utils/activityId.d.ts +2 -0
- package/dist/types/utils/apiUtils.d.ts +95 -0
- package/dist/types/utils/asyncUtils.d.ts +62 -0
- package/dist/types/utils/authHelpers.d.ts +58 -0
- package/dist/types/utils/authWebUrl.d.ts +16 -0
- package/dist/types/utils/avatarUtils.d.ts +16 -0
- package/dist/types/utils/cache.d.ts +130 -0
- package/dist/types/utils/cacheKey.d.ts +66 -0
- package/dist/types/utils/coldBoot.d.ts +131 -0
- package/dist/types/utils/commonsApproval.d.ts +13 -0
- package/dist/types/utils/commonsDelivery.d.ts +105 -0
- package/dist/types/utils/deviceManager.d.ts +65 -0
- package/dist/types/utils/displayNamePolicyRanges.generated.d.ts +57 -0
- package/dist/types/utils/edgeRegion.d.ts +2 -0
- package/dist/types/utils/errorUtils.d.ts +125 -0
- package/dist/types/utils/identityCacheSweep.d.ts +80 -0
- package/dist/types/utils/languageUtils.d.ts +100 -0
- package/dist/types/utils/oauthPkce.d.ts +157 -0
- package/dist/types/utils/officialOrigins.d.ts +13 -0
- package/dist/types/utils/oxyServiceEnvironment.d.ts +17 -0
- package/dist/types/utils/platform.d.ts +49 -0
- package/dist/types/utils/profileLinks.d.ts +44 -0
- package/dist/types/utils/redactUrl.d.ts +17 -0
- package/dist/types/utils/registrableApex.d.ts +27 -0
- package/dist/types/utils/requestUtils.d.ts +123 -0
- package/dist/types/utils/sessionUtils.d.ts +54 -0
- package/dist/types/utils/textNormalization.d.ts +103 -0
- package/dist/types/utils/userHandle.d.ts +26 -0
- package/dist/types/utils/userIdentity.d.ts +21 -0
- package/dist/types/utils/validationUtils.d.ts +268 -0
- package/dist/types/utils/webauthnOrigin.d.ts +32 -0
- package/package.json +168 -0
- package/src/HttpService.ts +1553 -0
- package/src/OxyServices.base.ts +478 -0
- package/src/OxyServices.errors.ts +122 -0
- package/src/OxyServices.ts +172 -0
- package/src/__tests__/authSocket.test.ts +96 -0
- package/src/__tests__/httpServiceActivityId.test.ts +49 -0
- package/src/__tests__/httpServiceAuthSelfAwait.test.ts +108 -0
- package/src/__tests__/httpServiceCache.test.ts +318 -0
- package/src/__tests__/httpServiceCsrf.test.ts +235 -0
- package/src/__tests__/httpServiceFormEncoded.test.ts +142 -0
- package/src/__tests__/httpServiceQueueDeadlock.test.ts +128 -0
- package/src/__tests__/httpServiceUnwrapEnvelope.test.ts +115 -0
- package/src/__tests__/inSessionRefresh.test.ts +260 -0
- package/src/__tests__/linkedClient.test.ts +370 -0
- package/src/__tests__/parseHttpErrorBody.test.ts +116 -0
- package/src/__tests__/serverValueImportsDeclared.test.ts +120 -0
- package/src/__tests__/userIdentity.test.ts +143 -0
- package/src/boot/__tests__/sessionColdBoot.identity.test.ts +393 -0
- package/src/boot/__tests__/sessionColdBoot.sharedDevice.test.ts +325 -0
- package/src/boot/__tests__/sessionColdBoot.test.ts +570 -0
- package/src/boot/sessionColdBoot.ts +529 -0
- package/src/constants/version.ts +15 -0
- package/src/crypto/__tests__/backupMaterial.test.ts +86 -0
- package/src/crypto/__tests__/cryptoPrimitives.test.ts +226 -0
- package/src/crypto/__tests__/identityMocks.ts +125 -0
- package/src/crypto/__tests__/keyManager.atomicity.test.ts +272 -0
- package/src/crypto/__tests__/keyManager.cacheSafety.test.ts +175 -0
- package/src/crypto/__tests__/keyManager.identityStatus.test.ts +217 -0
- package/src/crypto/__tests__/keyManager.recoveryLadder.test.ts +179 -0
- package/src/crypto/__tests__/keyManager.recoveryMnemonic.test.ts +138 -0
- package/src/crypto/__tests__/keyManager.storageMigration.test.ts +227 -0
- package/src/crypto/__tests__/keyManager.test.ts +329 -0
- package/src/crypto/__tests__/polyfill.test.ts +109 -0
- package/src/crypto/__tests__/recoveryPhrase.test.ts +61 -0
- package/src/crypto/__tests__/scopedSeed.test.ts +126 -0
- package/src/crypto/__tests__/signChallengeShared.test.ts +63 -0
- package/src/crypto/__tests__/signedRecord.test.ts +230 -0
- package/src/crypto/aead.ts +97 -0
- package/src/crypto/ecdh.ts +37 -0
- package/src/crypto/identityMarker.ts +291 -0
- package/src/crypto/kdf.ts +43 -0
- package/src/crypto/keyManager.ts +2607 -0
- package/src/crypto/polyfill.ts +143 -0
- package/src/crypto/recoveryPhrase.ts +337 -0
- package/src/crypto/signatureService.ts +350 -0
- package/src/i18n/__tests__/accountCategoryLabels.test.ts +62 -0
- package/src/i18n/__tests__/accountRoleLabels.test.ts +54 -0
- package/src/i18n/__tests__/reputationCategoryLabels.test.ts +56 -0
- package/src/i18n/__tests__/trustTierLabels.test.ts +47 -0
- package/src/i18n/accountCategoryLabels.ts +44 -0
- package/src/i18n/accountRoleLabels.ts +26 -0
- package/src/i18n/index.ts +88 -0
- package/src/i18n/locales/ar-SA.json +282 -0
- package/src/i18n/locales/ca-ES.json +282 -0
- package/src/i18n/locales/de-DE.json +282 -0
- package/src/i18n/locales/en-US.json +2161 -0
- package/src/i18n/locales/es-ES.json +2161 -0
- package/src/i18n/locales/fr-FR.json +282 -0
- package/src/i18n/locales/it-IT.json +282 -0
- package/src/i18n/locales/ja-JP.json +282 -0
- package/src/i18n/locales/ko-KR.json +282 -0
- package/src/i18n/locales/pt-PT.json +282 -0
- package/src/i18n/locales/zh-CN.json +282 -0
- package/src/i18n/reputationCategoryLabels.ts +20 -0
- package/src/i18n/trustTierLabels.ts +18 -0
- package/src/index.ts +881 -0
- package/src/inference/OxyInferenceClient.ts +888 -0
- package/src/inference/__tests__/OxyInferenceClient.test.ts +834 -0
- package/src/logger/__tests__/logger.test.ts +207 -0
- package/src/logger/index.ts +217 -0
- package/src/mixins/OxyServices.accounts.ts +1330 -0
- package/src/mixins/OxyServices.analytics.ts +53 -0
- package/src/mixins/OxyServices.appData.ts +158 -0
- package/src/mixins/OxyServices.assets.ts +861 -0
- package/src/mixins/OxyServices.auth.ts +1858 -0
- package/src/mixins/OxyServices.chains.ts +134 -0
- package/src/mixins/OxyServices.civic.ts +945 -0
- package/src/mixins/OxyServices.connectedApps.ts +174 -0
- package/src/mixins/OxyServices.contacts.ts +73 -0
- package/src/mixins/OxyServices.deviceBoot.ts +210 -0
- package/src/mixins/OxyServices.deviceTransfer.ts +393 -0
- package/src/mixins/OxyServices.devices.ts +120 -0
- package/src/mixins/OxyServices.features.ts +454 -0
- package/src/mixins/OxyServices.followGraph.ts +293 -0
- package/src/mixins/OxyServices.identity.ts +705 -0
- package/src/mixins/OxyServices.identityBackup.ts +250 -0
- package/src/mixins/OxyServices.inference.ts +57 -0
- package/src/mixins/OxyServices.language.ts +144 -0
- package/src/mixins/OxyServices.links.ts +107 -0
- package/src/mixins/OxyServices.location.ts +46 -0
- package/src/mixins/OxyServices.nodes.ts +337 -0
- package/src/mixins/OxyServices.notifications.ts +142 -0
- package/src/mixins/OxyServices.payment.ts +163 -0
- package/src/mixins/OxyServices.privacy.ts +219 -0
- package/src/mixins/OxyServices.reputation.ts +436 -0
- package/src/mixins/OxyServices.security.ts +110 -0
- package/src/mixins/OxyServices.store.ts +585 -0
- package/src/mixins/OxyServices.topics.ts +169 -0
- package/src/mixins/OxyServices.user.ts +1137 -0
- package/src/mixins/OxyServices.utility.ts +1370 -0
- package/src/mixins/__tests__/OxyServices.civic.test.ts +1095 -0
- package/src/mixins/__tests__/OxyServices.deviceBoot.test.ts +124 -0
- package/src/mixins/__tests__/OxyServices.deviceTransfer.test.ts +271 -0
- package/src/mixins/__tests__/OxyServices.identity.test.ts +376 -0
- package/src/mixins/__tests__/OxyServices.links.test.ts +154 -0
- package/src/mixins/__tests__/OxyServices.nodes.test.ts +341 -0
- package/src/mixins/__tests__/OxyServices.rotateKey.test.ts +276 -0
- package/src/mixins/__tests__/OxyServices.serviceAssetMetadata.test.ts +192 -0
- package/src/mixins/__tests__/OxyServices.serviceAssetMetadataBySha.test.ts +135 -0
- package/src/mixins/__tests__/accounts.test.ts +727 -0
- package/src/mixins/__tests__/appData.test.ts +203 -0
- package/src/mixins/__tests__/assetCredentials.test.ts +47 -0
- package/src/mixins/__tests__/assetUpload.test.ts +191 -0
- package/src/mixins/__tests__/backgroundCredential.httpIntegration.test.ts +135 -0
- package/src/mixins/__tests__/chains.test.ts +113 -0
- package/src/mixins/__tests__/commonsSignIn.test.ts +1144 -0
- package/src/mixins/__tests__/connectedApps.test.ts +123 -0
- package/src/mixins/__tests__/deviceTokenMintPinned.test.ts +113 -0
- package/src/mixins/__tests__/discoveryErrorHandling.test.ts +266 -0
- package/src/mixins/__tests__/followCacheInvalidation.test.ts +173 -0
- package/src/mixins/__tests__/followGraph.test.ts +147 -0
- package/src/mixins/__tests__/followGraphPagination.test.ts +271 -0
- package/src/mixins/__tests__/getFileDownloadUrl.test.ts +346 -0
- package/src/mixins/__tests__/getFollowStatuses.test.ts +95 -0
- package/src/mixins/__tests__/getUsersByIds.test.ts +149 -0
- package/src/mixins/__tests__/identityBackup.test.ts +315 -0
- package/src/mixins/__tests__/identityWriteCacheInvalidation.test.ts +407 -0
- package/src/mixins/__tests__/inferenceFactory.test.ts +58 -0
- package/src/mixins/__tests__/onTokensChanged.test.ts +129 -0
- package/src/mixins/__tests__/preSessionSkipAuth.test.ts +284 -0
- package/src/mixins/__tests__/privacyCacheInvalidation.test.ts +155 -0
- package/src/mixins/__tests__/reputation.test.ts +522 -0
- package/src/mixins/__tests__/serviceAuth.test.ts +832 -0
- package/src/mixins/__tests__/serviceTokenJwks.test.ts +208 -0
- package/src/mixins/__tests__/store.test.ts +304 -0
- package/src/mixins/__tests__/topics.test.ts +156 -0
- package/src/mixins/__tests__/userReadCacheBypass.test.ts +129 -0
- package/src/mixins/__tests__/userTokenAuth.test.ts +746 -0
- package/src/mixins/__tests__/verifyChallenge.test.ts +130 -0
- package/src/mixins/__tests__/verifyServiceActingAs.test.ts +167 -0
- package/src/mixins/__tests__/webauthnAuth.test.ts +205 -0
- package/src/mixins/index.ts +201 -0
- package/src/mixins/mixinHelpers.ts +69 -0
- package/src/models/Topic.ts +46 -0
- package/src/models/interfaces.ts +786 -0
- package/src/models/session.ts +55 -0
- package/src/server/__tests__/auth.test.ts +78 -0
- package/src/server/__tests__/capabilityTicket.test.ts +111 -0
- package/src/server/__tests__/cors.socket.test.ts +225 -0
- package/src/server/__tests__/cors.test.ts +158 -0
- package/src/server/__tests__/rateLimit.test.ts +257 -0
- package/src/server/__tests__/safeFetch.test.ts +232 -0
- package/src/server/__tests__/securityHeaders.test.ts +348 -0
- package/src/server/__tests__/serviceTokenAttribution.test.ts +396 -0
- package/src/server/__tests__/userInvalidation.test.ts +203 -0
- package/src/server/__tests__/verifySecret.test.ts +40 -0
- package/src/server/auth.ts +271 -0
- package/src/server/capabilityTicket.ts +258 -0
- package/src/server/cors.ts +277 -0
- package/src/server/index.ts +136 -0
- package/src/server/rateLimit.ts +313 -0
- package/src/server/safeFetch.ts +586 -0
- package/src/server/securityHeaders.ts +467 -0
- package/src/server/userInvalidation.ts +199 -0
- package/src/server/verifySecret.ts +52 -0
- package/src/session/SessionClient.ts +1001 -0
- package/src/session/__tests__/SessionClient.additive.test.ts +153 -0
- package/src/session/__tests__/SessionClient.broadcastChannel.test.ts +114 -0
- package/src/session/__tests__/SessionClient.diagnostics.test.ts +91 -0
- package/src/session/__tests__/SessionClient.directory.test.ts +688 -0
- package/src/session/__tests__/SessionClient.httpIntegration.test.ts +65 -0
- package/src/session/__tests__/SessionClient.identityPin.test.ts +175 -0
- package/src/session/__tests__/SessionClient.rest.test.ts +119 -0
- package/src/session/__tests__/SessionClient.serverEvents.test.ts +72 -0
- package/src/session/__tests__/SessionClient.socket.test.ts +202 -0
- package/src/session/__tests__/SessionClient.socketFactory.test.ts +81 -0
- package/src/session/__tests__/SessionClient.state.test.ts +78 -0
- package/src/session/__tests__/SessionClient.switchTokenOrder.test.ts +170 -0
- package/src/session/__tests__/accountDelegationAccess.test.ts +104 -0
- package/src/session/__tests__/accountDialogController.test.ts +1969 -0
- package/src/session/__tests__/accountDialogShape.test.ts +118 -0
- package/src/session/__tests__/accountSwitchTargets.test.ts +137 -0
- package/src/session/__tests__/authStateStore.test.ts +451 -0
- package/src/session/__tests__/deviceDirectory.test.ts +422 -0
- package/src/session/__tests__/deviceSwitcherRows.test.ts +223 -0
- package/src/session/__tests__/identityPin.test.ts +131 -0
- package/src/session/__tests__/identitySession.test.ts +194 -0
- package/src/session/__tests__/projectSessionState.test.ts +105 -0
- package/src/session/__tests__/refresh.identityPin.test.ts +307 -0
- package/src/session/__tests__/refresh.test.ts +443 -0
- package/src/session/__tests__/sessionIntegration.test.ts +209 -0
- package/src/session/__tests__/sharedDeviceCredential.test.ts +300 -0
- package/src/session/accountDelegationAccess.ts +72 -0
- package/src/session/accountDialogController.ts +1494 -0
- package/src/session/accountSwitchTargets.ts +93 -0
- package/src/session/authStateStore.ts +502 -0
- package/src/session/createSessionClient.ts +39 -0
- package/src/session/deviceDirectory.ts +269 -0
- package/src/session/deviceSwitcherRows.ts +145 -0
- package/src/session/identityPin.ts +310 -0
- package/src/session/identitySession.ts +206 -0
- package/src/session/projectSessionState.ts +137 -0
- package/src/session/refresh.ts +517 -0
- package/src/session/sessionClientHost.ts +39 -0
- package/src/session/sharedDeviceCredential.ts +349 -0
- package/src/session/socketLoader.ts +30 -0
- package/src/shared/utils/colorUtils.ts +155 -0
- package/src/shared/utils/errorUtils.ts +181 -0
- package/src/shared/utils/index.ts +59 -0
- package/src/shared/utils/networkUtils.ts +248 -0
- package/src/shared/utils/themeUtils.ts +115 -0
- package/src/types/buffer.d.ts +97 -0
- package/src/types/expo-crypto.d.ts +16 -0
- package/src/types/expo-secure-store.d.ts +17 -0
- package/src/utils/__tests__/accountUtils.test.ts +151 -0
- package/src/utils/__tests__/activityId.test.ts +45 -0
- package/src/utils/__tests__/asyncUtils.test.ts +187 -0
- package/src/utils/__tests__/authWebUrl.test.ts +15 -0
- package/src/utils/__tests__/cacheKey.test.ts +0 -0
- package/src/utils/__tests__/coldBoot.test.ts +496 -0
- package/src/utils/__tests__/commonsApproval.test.ts +60 -0
- package/src/utils/__tests__/identityCacheSweep.test.ts +151 -0
- package/src/utils/__tests__/languageUtils.test.ts +219 -0
- package/src/utils/__tests__/oauthPkce.test.ts +272 -0
- package/src/utils/__tests__/officialOrigins.test.ts +31 -0
- package/src/utils/__tests__/oxyServiceEnvironment.test.ts +7 -0
- package/src/utils/__tests__/profileLinks.test.ts +180 -0
- package/src/utils/__tests__/redactUrl.test.ts +33 -0
- package/src/utils/__tests__/registrableApex.test.ts +62 -0
- package/src/utils/__tests__/textNormalization.test.ts +205 -0
- package/src/utils/__tests__/validationUtils.test.ts +703 -0
- package/src/utils/__tests__/webauthnOrigin.test.ts +83 -0
- package/src/utils/accountCacheSweep.ts +93 -0
- package/src/utils/accountUtils.ts +194 -0
- package/src/utils/activityId.ts +2 -0
- package/src/utils/apiUtils.ts +137 -0
- package/src/utils/asyncUtils.ts +280 -0
- package/src/utils/authHelpers.ts +148 -0
- package/src/utils/authWebUrl.ts +17 -0
- package/src/utils/avatarUtils.ts +39 -0
- package/src/utils/cache.ts +273 -0
- package/src/utils/cacheKey.ts +93 -0
- package/src/utils/coldBoot.ts +218 -0
- package/src/utils/commonsApproval.ts +39 -0
- package/src/utils/commonsDelivery.ts +132 -0
- package/src/utils/deviceManager.ts +203 -0
- package/src/utils/displayNamePolicyRanges.generated.ts +69 -0
- package/src/utils/edgeRegion.ts +2 -0
- package/src/utils/errorUtils.ts +352 -0
- package/src/utils/identityCacheSweep.ts +104 -0
- package/src/utils/languageUtils.ts +256 -0
- package/src/utils/oauthPkce.ts +392 -0
- package/src/utils/officialOrigins.ts +62 -0
- package/src/utils/oxyServiceEnvironment.ts +17 -0
- package/src/utils/platform.ts +139 -0
- package/src/utils/profileLinks.ts +91 -0
- package/src/utils/redactUrl.ts +28 -0
- package/src/utils/registrableApex.ts +41 -0
- package/src/utils/requestUtils.ts +237 -0
- package/src/utils/sessionUtils.ts +206 -0
- package/src/utils/textNormalization.ts +162 -0
- package/src/utils/userHandle.ts +49 -0
- package/src/utils/userIdentity.ts +60 -0
- package/src/utils/validationUtils.ts +390 -0
- package/src/utils/webauthnOrigin.ts +52 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Strict CORS allowlist for Oxy backends.
|
|
4
|
+
*
|
|
5
|
+
* WHY THIS EXISTS
|
|
6
|
+
* ---------------
|
|
7
|
+
* App backends kept hand-rolling CORS, and the unsafe patterns recurred:
|
|
8
|
+
* - `Access-Control-Allow-Origin: *` together with credentials (which is
|
|
9
|
+
* spec-invalid AND a credential-leak vector), or
|
|
10
|
+
* - a "reflect whatever Origin the request carried" fallback (effectively
|
|
11
|
+
* `*` for credentialed requests — the Allo wildcard-fallback class).
|
|
12
|
+
*
|
|
13
|
+
* `createOxyCors` returns a self-contained Express middleware (no `cors`
|
|
14
|
+
* package dependency) that:
|
|
15
|
+
* - allows the Oxy apex origin family over HTTPS only: the apex plus
|
|
16
|
+
* one-label subdomains such as `auth.oxy.so`, `api.oxy.so`,
|
|
17
|
+
* `accounts.oxy.so`, `console.oxy.so`, and `inbox.oxy.so`,
|
|
18
|
+
* - allows the caller's explicit `appOrigins`,
|
|
19
|
+
* - REFUSES the opaque origin on both sides (see `OPAQUE_ORIGIN`),
|
|
20
|
+
* - DENIES everything else (no reflection, never a wildcard with credentials),
|
|
21
|
+
* - echoes back the EXACT matched origin (so credentialed requests work) and
|
|
22
|
+
* sets `Vary: Origin` for correct caching,
|
|
23
|
+
* - answers CORS preflight (`OPTIONS`) with `204`.
|
|
24
|
+
*
|
|
25
|
+
* Node/Express-only: exported solely from `@oxy.so/core/server`.
|
|
26
|
+
*/
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.normalizeAppOrigins = normalizeAppOrigins;
|
|
29
|
+
exports.matchesAllowedOrigin = matchesAllowedOrigin;
|
|
30
|
+
exports.createOxyCors = createOxyCors;
|
|
31
|
+
const logger_1 = require("../logger");
|
|
32
|
+
const authWebUrl_1 = require("../utils/authWebUrl");
|
|
33
|
+
const log = (0, logger_1.createLogger)('OxyCors');
|
|
34
|
+
/** Default HTTP methods allowed across origins. */
|
|
35
|
+
const DEFAULT_ALLOWED_METHODS = ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE', 'OPTIONS'];
|
|
36
|
+
/** Default request headers a browser may send on a credentialed cross-origin call. */
|
|
37
|
+
const DEFAULT_ALLOWED_HEADERS = [
|
|
38
|
+
'Content-Type',
|
|
39
|
+
'Authorization',
|
|
40
|
+
'X-Requested-With',
|
|
41
|
+
'X-Oxy-User-Id',
|
|
42
|
+
'X-Oxy-Internal',
|
|
43
|
+
'X-CSRF-Token',
|
|
44
|
+
'X-Oxy-Edge-Region',
|
|
45
|
+
'X-Oxy-Activity-Id',
|
|
46
|
+
];
|
|
47
|
+
/** How long (seconds) a browser may cache a successful preflight. */
|
|
48
|
+
const DEFAULT_MAX_AGE_SECONDS = 86400;
|
|
49
|
+
const OXY_ONE_LABEL_SUBDOMAIN_PATTERN = new RegExp(`^[a-z0-9-]+\\.${authWebUrl_1.CENTRAL_IDP_APEX.replace('.', '\\.')}$`);
|
|
50
|
+
/**
|
|
51
|
+
* Whether `candidate` belongs to the built-in Oxy apex origin family. This
|
|
52
|
+
* intentionally mirrors the API allowlist shape: HTTPS only, no custom port,
|
|
53
|
+
* the apex itself (`https://oxy.so`), or exactly one lowercase subdomain label
|
|
54
|
+
* (`https://auth.oxy.so`, `https://api.oxy.so`, …).
|
|
55
|
+
*
|
|
56
|
+
* Arbitrary/multi-level subdomains and `http://*.oxy.so` are not implicitly
|
|
57
|
+
* trusted for credentialed CORS. If a service needs a non-standard development
|
|
58
|
+
* or tenant origin, it must opt in explicitly via `appOrigins`.
|
|
59
|
+
*/
|
|
60
|
+
function isOxyFamilyOrigin(candidate) {
|
|
61
|
+
try {
|
|
62
|
+
const url = new URL(candidate);
|
|
63
|
+
if (url.protocol !== 'https:' || url.port !== '')
|
|
64
|
+
return false;
|
|
65
|
+
const hostname = url.hostname;
|
|
66
|
+
if (hostname === authWebUrl_1.CENTRAL_IDP_APEX)
|
|
67
|
+
return true;
|
|
68
|
+
return OXY_ONE_LABEL_SUBDOMAIN_PATTERN.test(hostname);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The URL standard's serialization of an OPAQUE origin: the literal string
|
|
76
|
+
* `"null"`, which `new URL(x).origin` returns for every scheme that has no
|
|
77
|
+
* origin to speak of — `exp:`, `capacitor:`, `chrome-extension:`,
|
|
78
|
+
* `vscode-webview:`, and also `file:`, `data:` and `about:`.
|
|
79
|
+
*
|
|
80
|
+
* This value is why an allowlist may never store it. Every such scheme
|
|
81
|
+
* normalizes to the SAME `"null"`, so a set built by normalization cannot tell
|
|
82
|
+
* them apart: ONE opaque entry admits ALL of them. With credentials on and the
|
|
83
|
+
* raw header echoed back, a single `myapp://` in `appOrigins` turned this
|
|
84
|
+
* helper into "allow any custom-scheme browsing context" — measured live, an
|
|
85
|
+
* `exp://localhost:8150` entry answered `Origin: vscode-webview://…` with
|
|
86
|
+
* `access-control-allow-origin: vscode-webview://…` and
|
|
87
|
+
* `access-control-allow-credentials: true`.
|
|
88
|
+
*
|
|
89
|
+
* There is deliberately no escape hatch that matches such an origin by raw
|
|
90
|
+
* string instead. Admitting a custom-scheme browsing context to a CREDENTIALED
|
|
91
|
+
* allowlist is a distinct decision with its own threat model, and it must not
|
|
92
|
+
* arrive as a side effect of someone adding one line to `appOrigins`. Note
|
|
93
|
+
* also that a native client is not subject to CORS at all — React Native sends
|
|
94
|
+
* no `Origin` header — so a mobile app never needs an entry here.
|
|
95
|
+
*/
|
|
96
|
+
const OPAQUE_ORIGIN = 'null';
|
|
97
|
+
/** Normalize a raw origin string to its canonical `scheme://host[:port]` form. */
|
|
98
|
+
function normalizeOrigin(raw) {
|
|
99
|
+
try {
|
|
100
|
+
return new URL(raw).origin;
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Normalize the configured `appOrigins` into the exact-match set — the
|
|
108
|
+
* CONFIGURE-SIDE half of the opaque-origin guard.
|
|
109
|
+
*
|
|
110
|
+
* An entry that is not a URL, or whose origin is opaque, is dropped and named
|
|
111
|
+
* in an error log. Dropped rather than thrown on because `appOrigins` is
|
|
112
|
+
* deployment configuration — at least one Oxy backend reads it from the
|
|
113
|
+
* environment — and a typo there must cost that one origin its CORS headers,
|
|
114
|
+
* never the whole service its boot. Both failure modes are equally SAFE (the
|
|
115
|
+
* entry is absent from the set either way), so the choice is purely about
|
|
116
|
+
* blast radius, and dropping keeps it to one origin whose requests then fail
|
|
117
|
+
* visibly in the browser.
|
|
118
|
+
*
|
|
119
|
+
* Exported for `__tests__/cors.socket.test.ts` and NOT re-exported from
|
|
120
|
+
* `server/index.ts`, so it is not part of the package's public surface. The
|
|
121
|
+
* two halves of the guard are separately exported because they are separately
|
|
122
|
+
* testable only that way: with this half in place the match-side half is
|
|
123
|
+
* unreachable through `createOxyCors`, so a test driving the public API alone
|
|
124
|
+
* would measure this function twice and the other one never.
|
|
125
|
+
*/
|
|
126
|
+
function normalizeAppOrigins(appOrigins) {
|
|
127
|
+
const explicit = new Set();
|
|
128
|
+
for (const raw of appOrigins) {
|
|
129
|
+
const normalized = normalizeOrigin(raw);
|
|
130
|
+
if (normalized === null) {
|
|
131
|
+
log.error('CORS allowlist entry ignored: it is not a URL', undefined, { entry: raw });
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (normalized === OPAQUE_ORIGIN) {
|
|
135
|
+
log.error('CORS allowlist entry ignored: it has no origin to match against', undefined, {
|
|
136
|
+
entry: raw,
|
|
137
|
+
});
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
explicit.add(normalized);
|
|
141
|
+
}
|
|
142
|
+
return explicit;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Whether `origin` may be echoed back: it is in the built-in HTTPS Oxy apex
|
|
146
|
+
* family, or it exactly matches one of the configured app origins.
|
|
147
|
+
*
|
|
148
|
+
* The opaque-origin refusal here is the MATCH-SIDE half of the guard, and it
|
|
149
|
+
* is what makes the property hold regardless of how `explicit` was built — a
|
|
150
|
+
* set that somehow contains `"null"` still matches nothing, because no
|
|
151
|
+
* incoming origin ever normalizes past this line. `normalizeAppOrigins` is
|
|
152
|
+
* what stops such a set existing today; this is what stops it mattering.
|
|
153
|
+
*
|
|
154
|
+
* Exported for the same reason as `normalizeAppOrigins`, and likewise absent
|
|
155
|
+
* from `server/index.ts`.
|
|
156
|
+
*/
|
|
157
|
+
function matchesAllowedOrigin(explicit, origin) {
|
|
158
|
+
const normalized = normalizeOrigin(origin);
|
|
159
|
+
if (normalized === null)
|
|
160
|
+
return false;
|
|
161
|
+
if (normalized === OPAQUE_ORIGIN)
|
|
162
|
+
return false;
|
|
163
|
+
if (explicit.has(normalized))
|
|
164
|
+
return true;
|
|
165
|
+
return isOxyFamilyOrigin(normalized);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Create a strict Oxy CORS middleware. See module docs.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* app.use(createOxyCors({ appOrigins: ['https://app.example.com'] }));
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
function createOxyCors(options = {}) {
|
|
176
|
+
const { appOrigins = [], allowCredentials = true, methods = DEFAULT_ALLOWED_METHODS, allowedHeaders = DEFAULT_ALLOWED_HEADERS, exposedHeaders = [], maxAgeSeconds = DEFAULT_MAX_AGE_SECONDS, } = options;
|
|
177
|
+
const explicitOrigins = normalizeAppOrigins(appOrigins);
|
|
178
|
+
const methodsHeader = methods.join(', ');
|
|
179
|
+
const allowedHeadersHeader = allowedHeaders.join(', ');
|
|
180
|
+
const exposedHeadersHeader = exposedHeaders.join(', ');
|
|
181
|
+
return (req, res, next) => {
|
|
182
|
+
const origin = req.headers.origin;
|
|
183
|
+
// Same-origin or non-browser requests carry no Origin header — pass through
|
|
184
|
+
// untouched (no ACAO header is emitted, which is correct for them).
|
|
185
|
+
if (typeof origin !== 'string' || origin.length === 0) {
|
|
186
|
+
if (req.method === 'OPTIONS') {
|
|
187
|
+
res.sendStatus(204);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
next();
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
// Origin is present. Caching correctness: this response varies by Origin.
|
|
194
|
+
res.setHeader('Vary', 'Origin');
|
|
195
|
+
if (!matchesAllowedOrigin(explicitOrigins, origin)) {
|
|
196
|
+
// DENY: do NOT reflect the origin, do NOT emit a wildcard. The browser
|
|
197
|
+
// will block the cross-origin read. Preflights for denied origins get a
|
|
198
|
+
// 204 with no CORS headers (the actual request then fails CORS).
|
|
199
|
+
if (req.method === 'OPTIONS') {
|
|
200
|
+
res.sendStatus(204);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
next();
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
// ALLOW: echo the EXACT matched origin — never `*`, even without credentials.
|
|
207
|
+
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
208
|
+
if (allowCredentials) {
|
|
209
|
+
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
|
210
|
+
}
|
|
211
|
+
if (exposedHeadersHeader) {
|
|
212
|
+
res.setHeader('Access-Control-Expose-Headers', exposedHeadersHeader);
|
|
213
|
+
}
|
|
214
|
+
if (req.method === 'OPTIONS') {
|
|
215
|
+
res.setHeader('Access-Control-Allow-Methods', methodsHeader);
|
|
216
|
+
// Honour the browser's requested headers when present, else the default set.
|
|
217
|
+
const requested = req.headers['access-control-request-headers'];
|
|
218
|
+
res.setHeader('Access-Control-Allow-Headers', typeof requested === 'string' && requested.length > 0 ? requested : allowedHeadersHeader);
|
|
219
|
+
res.setHeader('Access-Control-Max-Age', String(maxAgeSeconds));
|
|
220
|
+
res.sendStatus(204);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
next();
|
|
224
|
+
};
|
|
225
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @oxy.so/core/server — Server-only utilities for Oxy backends
|
|
4
|
+
*
|
|
5
|
+
* This subpath export provides Express middleware and Node.js-specific
|
|
6
|
+
* utilities that are not available in React Native or browser environments.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { createOxyRateLimit } from '@oxy.so/core/server';
|
|
11
|
+
* import { oxyClient } from '@oxy.so/core';
|
|
12
|
+
*
|
|
13
|
+
* const oxy = oxyClient({ apiUrl: 'https://api.oxy.so' });
|
|
14
|
+
*
|
|
15
|
+
* app.use(createOxyRateLimit(oxy, { store: redisStore }));
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.isOfficialWebOrigin = exports.registrableApex = exports.OXY_IDENTITY_CACHE_PREFIXES = exports.oxyUserByIdCacheKey = exports.evictOxyIdentityCache = exports.publishOxyUserInvalidation = exports.createOxyUserInvalidationHandler = exports.verifySecret = exports.verifyCapabilityTicket = exports.readCapabilityAuthorization = exports.issueCapabilityTicket = exports.inputSatisfiesCapabilityLimits = exports.createCapabilityTicketMiddleware = exports.CapabilityTicketError = exports.OXY_CSP_BASELINE = exports.inlineScriptCspHash = exports.formatOxyCspPolicy = exports.extractInlineScripts = exports.cspSourcesFor = exports.createOxySecurityHeaders = exports.buildOxyPagesHeaders = exports.buildOxyCspDirectives = exports.createOxyCors = exports.UPSTREAM_HEADERS_TIMEOUT_MS = exports.MAX_URL_LENGTH = exports.MAX_REDIRECTS = exports.DEFAULT_USER_AGENT = exports.BLOCKED_HOSTNAMES = exports.ALLOWED_PROTOCOLS = exports.ALLOWED_PORTS = exports.UpstreamError = exports.SsrfRejection = exports.safeFetch = exports.isBlockedIp = exports.assertSafePublicUrl = exports.createOxyRateLimit = exports.OXY_SERVICE_ENVIRONMENTS = exports.requireOxyAuth = exports.isOxyAuthenticated = exports.getRequiredOxyUserId = exports.getRequiredOxyBillingPrincipal = exports.getOxyUserId = exports.getOxyRequestAttribution = exports.getOxyDelegatedUserId = exports.getOxyBillingPrincipal = exports.createOxyAuthMiddleware = exports.createOptionalOxyAuth = void 0;
|
|
20
|
+
var auth_1 = require("./auth");
|
|
21
|
+
Object.defineProperty(exports, "createOptionalOxyAuth", { enumerable: true, get: function () { return auth_1.createOptionalOxyAuth; } });
|
|
22
|
+
Object.defineProperty(exports, "createOxyAuthMiddleware", { enumerable: true, get: function () { return auth_1.createOxyAuthMiddleware; } });
|
|
23
|
+
Object.defineProperty(exports, "getOxyBillingPrincipal", { enumerable: true, get: function () { return auth_1.getOxyBillingPrincipal; } });
|
|
24
|
+
Object.defineProperty(exports, "getOxyDelegatedUserId", { enumerable: true, get: function () { return auth_1.getOxyDelegatedUserId; } });
|
|
25
|
+
Object.defineProperty(exports, "getOxyRequestAttribution", { enumerable: true, get: function () { return auth_1.getOxyRequestAttribution; } });
|
|
26
|
+
Object.defineProperty(exports, "getOxyUserId", { enumerable: true, get: function () { return auth_1.getOxyUserId; } });
|
|
27
|
+
Object.defineProperty(exports, "getRequiredOxyBillingPrincipal", { enumerable: true, get: function () { return auth_1.getRequiredOxyBillingPrincipal; } });
|
|
28
|
+
Object.defineProperty(exports, "getRequiredOxyUserId", { enumerable: true, get: function () { return auth_1.getRequiredOxyUserId; } });
|
|
29
|
+
Object.defineProperty(exports, "isOxyAuthenticated", { enumerable: true, get: function () { return auth_1.isOxyAuthenticated; } });
|
|
30
|
+
Object.defineProperty(exports, "requireOxyAuth", { enumerable: true, get: function () { return auth_1.requireOxyAuth; } });
|
|
31
|
+
Object.defineProperty(exports, "OXY_SERVICE_ENVIRONMENTS", { enumerable: true, get: function () { return auth_1.OXY_SERVICE_ENVIRONMENTS; } });
|
|
32
|
+
var rateLimit_1 = require("./rateLimit");
|
|
33
|
+
Object.defineProperty(exports, "createOxyRateLimit", { enumerable: true, get: function () { return rateLimit_1.createOxyRateLimit; } });
|
|
34
|
+
// SSRF-safe upstream fetch + URL validation (Node-only).
|
|
35
|
+
var safeFetch_1 = require("./safeFetch");
|
|
36
|
+
Object.defineProperty(exports, "assertSafePublicUrl", { enumerable: true, get: function () { return safeFetch_1.assertSafePublicUrl; } });
|
|
37
|
+
Object.defineProperty(exports, "isBlockedIp", { enumerable: true, get: function () { return safeFetch_1.isBlockedIp; } });
|
|
38
|
+
Object.defineProperty(exports, "safeFetch", { enumerable: true, get: function () { return safeFetch_1.safeFetch; } });
|
|
39
|
+
Object.defineProperty(exports, "SsrfRejection", { enumerable: true, get: function () { return safeFetch_1.SsrfRejection; } });
|
|
40
|
+
Object.defineProperty(exports, "UpstreamError", { enumerable: true, get: function () { return safeFetch_1.UpstreamError; } });
|
|
41
|
+
Object.defineProperty(exports, "ALLOWED_PORTS", { enumerable: true, get: function () { return safeFetch_1.ALLOWED_PORTS; } });
|
|
42
|
+
Object.defineProperty(exports, "ALLOWED_PROTOCOLS", { enumerable: true, get: function () { return safeFetch_1.ALLOWED_PROTOCOLS; } });
|
|
43
|
+
Object.defineProperty(exports, "BLOCKED_HOSTNAMES", { enumerable: true, get: function () { return safeFetch_1.BLOCKED_HOSTNAMES; } });
|
|
44
|
+
Object.defineProperty(exports, "DEFAULT_USER_AGENT", { enumerable: true, get: function () { return safeFetch_1.DEFAULT_USER_AGENT; } });
|
|
45
|
+
Object.defineProperty(exports, "MAX_REDIRECTS", { enumerable: true, get: function () { return safeFetch_1.MAX_REDIRECTS; } });
|
|
46
|
+
Object.defineProperty(exports, "MAX_URL_LENGTH", { enumerable: true, get: function () { return safeFetch_1.MAX_URL_LENGTH; } });
|
|
47
|
+
Object.defineProperty(exports, "UPSTREAM_HEADERS_TIMEOUT_MS", { enumerable: true, get: function () { return safeFetch_1.UPSTREAM_HEADERS_TIMEOUT_MS; } });
|
|
48
|
+
// Strict CORS allowlist (Oxy apex family + explicit app origins).
|
|
49
|
+
var cors_1 = require("./cors");
|
|
50
|
+
Object.defineProperty(exports, "createOxyCors", { enumerable: true, get: function () { return cors_1.createOxyCors; } });
|
|
51
|
+
// Shared Helmet + Content-Security-Policy baseline (Cloudflare Insights beacon,
|
|
52
|
+
// Oxy API/CDN origins) with additive, per-app extensions.
|
|
53
|
+
//
|
|
54
|
+
// `extractInlineScripts` / `inlineScriptCspHash` / `cspSourcesFor` are exported
|
|
55
|
+
// so a post-deploy gate can ask the SERVED document and the SERVED policy the
|
|
56
|
+
// same questions `buildOxyPagesHeaders` asked the built ones. A gate that
|
|
57
|
+
// re-implemented the scan or the parse would be testing its own copy, and would
|
|
58
|
+
// agree with a broken original.
|
|
59
|
+
var securityHeaders_1 = require("./securityHeaders");
|
|
60
|
+
Object.defineProperty(exports, "buildOxyCspDirectives", { enumerable: true, get: function () { return securityHeaders_1.buildOxyCspDirectives; } });
|
|
61
|
+
Object.defineProperty(exports, "buildOxyPagesHeaders", { enumerable: true, get: function () { return securityHeaders_1.buildOxyPagesHeaders; } });
|
|
62
|
+
Object.defineProperty(exports, "createOxySecurityHeaders", { enumerable: true, get: function () { return securityHeaders_1.createOxySecurityHeaders; } });
|
|
63
|
+
Object.defineProperty(exports, "cspSourcesFor", { enumerable: true, get: function () { return securityHeaders_1.cspSourcesFor; } });
|
|
64
|
+
Object.defineProperty(exports, "extractInlineScripts", { enumerable: true, get: function () { return securityHeaders_1.extractInlineScripts; } });
|
|
65
|
+
Object.defineProperty(exports, "formatOxyCspPolicy", { enumerable: true, get: function () { return securityHeaders_1.formatOxyCspPolicy; } });
|
|
66
|
+
Object.defineProperty(exports, "inlineScriptCspHash", { enumerable: true, get: function () { return securityHeaders_1.inlineScriptCspHash; } });
|
|
67
|
+
Object.defineProperty(exports, "OXY_CSP_BASELINE", { enumerable: true, get: function () { return securityHeaders_1.OXY_CSP_BASELINE; } });
|
|
68
|
+
var capabilityTicket_1 = require("./capabilityTicket");
|
|
69
|
+
Object.defineProperty(exports, "CapabilityTicketError", { enumerable: true, get: function () { return capabilityTicket_1.CapabilityTicketError; } });
|
|
70
|
+
Object.defineProperty(exports, "createCapabilityTicketMiddleware", { enumerable: true, get: function () { return capabilityTicket_1.createCapabilityTicketMiddleware; } });
|
|
71
|
+
Object.defineProperty(exports, "inputSatisfiesCapabilityLimits", { enumerable: true, get: function () { return capabilityTicket_1.inputSatisfiesCapabilityLimits; } });
|
|
72
|
+
Object.defineProperty(exports, "issueCapabilityTicket", { enumerable: true, get: function () { return capabilityTicket_1.issueCapabilityTicket; } });
|
|
73
|
+
Object.defineProperty(exports, "readCapabilityAuthorization", { enumerable: true, get: function () { return capabilityTicket_1.readCapabilityAuthorization; } });
|
|
74
|
+
Object.defineProperty(exports, "verifyCapabilityTicket", { enumerable: true, get: function () { return capabilityTicket_1.verifyCapabilityTicket; } });
|
|
75
|
+
// Constant-time secret comparison.
|
|
76
|
+
var verifySecret_1 = require("./verifySecret");
|
|
77
|
+
Object.defineProperty(exports, "verifySecret", { enumerable: true, get: function () { return verifySecret_1.verifySecret; } });
|
|
78
|
+
// Cross-service user-invalidation signal: oxy-api publishes when identity
|
|
79
|
+
// changes, every consuming backend sweeps its caches instead of waiting out a TTL.
|
|
80
|
+
var userInvalidation_1 = require("./userInvalidation");
|
|
81
|
+
Object.defineProperty(exports, "createOxyUserInvalidationHandler", { enumerable: true, get: function () { return userInvalidation_1.createOxyUserInvalidationHandler; } });
|
|
82
|
+
Object.defineProperty(exports, "publishOxyUserInvalidation", { enumerable: true, get: function () { return userInvalidation_1.publishOxyUserInvalidation; } });
|
|
83
|
+
// The identity-key enumeration itself is platform-neutral (`src/utils/`) so the
|
|
84
|
+
// client mixins and this Node-only subscriber sweep the SAME list — a second
|
|
85
|
+
// copy is what let `updateAccount` and `updateProfile` drift apart.
|
|
86
|
+
var identityCacheSweep_1 = require("../utils/identityCacheSweep");
|
|
87
|
+
Object.defineProperty(exports, "evictOxyIdentityCache", { enumerable: true, get: function () { return identityCacheSweep_1.evictOxyIdentityCache; } });
|
|
88
|
+
Object.defineProperty(exports, "oxyUserByIdCacheKey", { enumerable: true, get: function () { return identityCacheSweep_1.oxyUserByIdCacheKey; } });
|
|
89
|
+
Object.defineProperty(exports, "OXY_IDENTITY_CACHE_PREFIXES", { enumerable: true, get: function () { return identityCacheSweep_1.OXY_IDENTITY_CACHE_PREFIXES; } });
|
|
90
|
+
// Registrable-apex (eTLD+1) derivation via the Public Suffix List — the SINGLE
|
|
91
|
+
// SOURCE OF TRUTH shared with the IdP worker and the client FAPI auto-detect.
|
|
92
|
+
// Pure host handling (no browser deps), so it is safe on the server subpath and
|
|
93
|
+
// lets `@oxy.so/api` derive `auth.<apex>` without duplicating PSL logic.
|
|
94
|
+
var registrableApex_1 = require("../utils/registrableApex");
|
|
95
|
+
Object.defineProperty(exports, "registrableApex", { enumerable: true, get: function () { return registrableApex_1.registrableApex; } });
|
|
96
|
+
var officialOrigins_1 = require("../utils/officialOrigins");
|
|
97
|
+
Object.defineProperty(exports, "isOfficialWebOrigin", { enumerable: true, get: function () { return officialOrigins_1.isOfficialWebOrigin; } });
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createOxyRateLimit = createOxyRateLimit;
|
|
7
|
+
const node_crypto_1 = require("node:crypto");
|
|
8
|
+
const node_net_1 = require("node:net");
|
|
9
|
+
const express_rate_limit_1 = __importDefault(require("express-rate-limit"));
|
|
10
|
+
const auth_1 = require("./auth");
|
|
11
|
+
/**
|
|
12
|
+
* Built-in exemptions. A media app's cover-art/avatar fan-out and HLS
|
|
13
|
+
* sub-requests must not consume the coarse global budget; health probes from
|
|
14
|
+
* the load balancer must never be limited; CORS preflight is not a real call.
|
|
15
|
+
*/
|
|
16
|
+
function isBuiltInExempt(req) {
|
|
17
|
+
const path = req.path;
|
|
18
|
+
return (req.method === 'OPTIONS' ||
|
|
19
|
+
path.startsWith('/files/upload') ||
|
|
20
|
+
path.includes('/images/') ||
|
|
21
|
+
path.includes('/media/') ||
|
|
22
|
+
path.startsWith('/api/stream/') ||
|
|
23
|
+
path.includes('/stream/') ||
|
|
24
|
+
path === '/health' ||
|
|
25
|
+
path.endsWith('/health'));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Anonymous rate-limit keys must be PRIVACY-PRESERVING: the raw client IP must
|
|
29
|
+
* never reach a store at rest (in-memory or Redis). We therefore HMAC-hash the
|
|
30
|
+
* IP into a short, transient-only bucket key. Two IPv6-specific concerns shape
|
|
31
|
+
* the pre-hash normalization:
|
|
32
|
+
*
|
|
33
|
+
* - IPv6 hosts are typically handed an entire /64 (often a /56), so a single
|
|
34
|
+
* host can rotate through an enormous address space and evade a per-address
|
|
35
|
+
* limit. We bucket IPv6 to its /56 prefix BEFORE hashing.
|
|
36
|
+
* - express-rate-limit only exposes an `ipKeyGenerator` /56 helper from v8
|
|
37
|
+
* onwards; `@oxy.so/core` pins v7 (peer `^7.0.0`), so the masking is
|
|
38
|
+
* implemented here rather than pulling a major-version bump of a
|
|
39
|
+
* security-critical dependency (and its rate-limit-redis compatibility) into
|
|
40
|
+
* an unrelated privacy change. This mirrors `packages/api/src/utils/ipKey.ts`.
|
|
41
|
+
*/
|
|
42
|
+
const IPV6_SUBNET_BITS = 56;
|
|
43
|
+
/** Expand an IPv6 literal (handling `::` and embedded IPv4) to 8 numeric hextets, or null if unparseable. */
|
|
44
|
+
function ipv6Hextets(ip) {
|
|
45
|
+
let addr = ip;
|
|
46
|
+
const zone = addr.indexOf('%');
|
|
47
|
+
if (zone !== -1) {
|
|
48
|
+
addr = addr.slice(0, zone);
|
|
49
|
+
}
|
|
50
|
+
// Embedded IPv4 tail (e.g. `::ffff:203.0.113.7`) → fold the dotted quad into two hextets.
|
|
51
|
+
const lastColon = addr.lastIndexOf(':');
|
|
52
|
+
if (lastColon !== -1 && addr.slice(lastColon + 1).includes('.')) {
|
|
53
|
+
const v4 = addr.slice(lastColon + 1);
|
|
54
|
+
if (!(0, node_net_1.isIPv4)(v4)) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
const octets = v4.split('.').map((part) => Number.parseInt(part, 10));
|
|
58
|
+
const high = ((octets[0] << 8) | octets[1]).toString(16);
|
|
59
|
+
const low = ((octets[2] << 8) | octets[3]).toString(16);
|
|
60
|
+
addr = `${addr.slice(0, lastColon + 1)}${high}:${low}`;
|
|
61
|
+
}
|
|
62
|
+
const halves = addr.split('::');
|
|
63
|
+
if (halves.length > 2) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const head = halves[0] ? halves[0].split(':') : [];
|
|
67
|
+
const tail = halves.length === 2 && halves[1] ? halves[1].split(':') : [];
|
|
68
|
+
let groups;
|
|
69
|
+
if (halves.length === 1) {
|
|
70
|
+
groups = head;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
const missing = 8 - (head.length + tail.length);
|
|
74
|
+
if (missing < 0) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
groups = [...head, ...new Array(missing).fill('0'), ...tail];
|
|
78
|
+
}
|
|
79
|
+
if (groups.length !== 8) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
const hextets = groups.map((group) => Number.parseInt(group || '0', 16));
|
|
83
|
+
if (hextets.some((value) => Number.isNaN(value) || value < 0 || value > 0xffff)) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
return hextets;
|
|
87
|
+
}
|
|
88
|
+
/** Mask an IPv6 address to its /{bits} prefix, returned as a canonical hex string. */
|
|
89
|
+
function maskIPv6(ip, bits) {
|
|
90
|
+
const hextets = ipv6Hextets(ip);
|
|
91
|
+
if (!hextets) {
|
|
92
|
+
return ip;
|
|
93
|
+
}
|
|
94
|
+
const masked = hextets.map((hextet, index) => {
|
|
95
|
+
const groupStart = index * 16;
|
|
96
|
+
if (groupStart >= bits) {
|
|
97
|
+
return 0;
|
|
98
|
+
}
|
|
99
|
+
const keepBits = Math.min(16, bits - groupStart);
|
|
100
|
+
const mask = keepBits >= 16 ? 0xffff : (0xffff << (16 - keepBits)) & 0xffff;
|
|
101
|
+
return hextet & mask;
|
|
102
|
+
});
|
|
103
|
+
return `${masked.map((hextet) => hextet.toString(16)).join(':')}/${bits}`;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Hash a client IP into a privacy-preserving bucket key. IPv6 is bucketed to its
|
|
107
|
+
* /56 prefix first (so a single v6 host can't rotate through its allocation to
|
|
108
|
+
* mint fresh keys), then HMAC'd with the server-side salt. The salt is resolved
|
|
109
|
+
* at CALL time (`IP_HASH_SALT`, else `DEVICE_ID_SALT`, else empty) — an empty
|
|
110
|
+
* salt still hashes, which beats storing a raw IP; backends SHOULD set one of
|
|
111
|
+
* those envs. The `rl|` namespace ensures a rate-limit key can never collide
|
|
112
|
+
* with, or be correlated against, a deviceId derivation that reuses the same
|
|
113
|
+
* salt. The result is a short hex digest with no colons, so it is Redis-safe.
|
|
114
|
+
*/
|
|
115
|
+
function hashAnonymousIp(ip) {
|
|
116
|
+
const normalized = (0, node_net_1.isIPv6)(ip) && !ip.startsWith('::ffff:') ? maskIPv6(ip, IPV6_SUBNET_BITS) : ip;
|
|
117
|
+
const salt = process.env.IP_HASH_SALT || process.env.DEVICE_ID_SALT || '';
|
|
118
|
+
return (0, node_crypto_1.createHmac)('sha256', salt).update(`rl|${normalized}`).digest('hex').slice(0, 24);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Resolve the trusted authenticated rate-limit key.
|
|
122
|
+
*
|
|
123
|
+
* Only identities that came from a server-validated session or a verified
|
|
124
|
+
* service token/delegation may pick a bucket. `req.sessionId` is the marker
|
|
125
|
+
* for the former: `oxy.auth()` sets it only after `validateSession()` came
|
|
126
|
+
* back valid, so requiring it here means an identity written by some OTHER
|
|
127
|
+
* middleware — which this package cannot vouch for — shares the anonymous
|
|
128
|
+
* per-IP bucket rather than getting the authenticated quota.
|
|
129
|
+
*/
|
|
130
|
+
function resolveTrustedAuthenticatedKey(req) {
|
|
131
|
+
const userId = req.userId ?? req.user?.id ?? req.user?._id;
|
|
132
|
+
if (userId && req.sessionId) {
|
|
133
|
+
return `user:${userId}`;
|
|
134
|
+
}
|
|
135
|
+
const delegatedUserId = req.serviceActingAs?.userId;
|
|
136
|
+
if (delegatedUserId && req.serviceApp?.appId) {
|
|
137
|
+
return `user:${delegatedUserId}`;
|
|
138
|
+
}
|
|
139
|
+
const serviceAppId = req.serviceApp?.appId;
|
|
140
|
+
if (serviceAppId) {
|
|
141
|
+
return `service:${serviceAppId}`;
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
/** Resolve the rate-limit key: per trusted authenticated identity, else per hashed (IPv6-bucketed) IP. */
|
|
146
|
+
function resolveKey(req) {
|
|
147
|
+
const authenticatedKey = resolveTrustedAuthenticatedKey(req);
|
|
148
|
+
if (authenticatedKey) {
|
|
149
|
+
return authenticatedKey;
|
|
150
|
+
}
|
|
151
|
+
const ip = req.ip || req.socket.remoteAddress;
|
|
152
|
+
if (!ip) {
|
|
153
|
+
return 'unknown';
|
|
154
|
+
}
|
|
155
|
+
return hashAnonymousIp(ip);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Build the composed Oxy rate-limit middleware. See module docs for rationale.
|
|
159
|
+
*/
|
|
160
|
+
function createOxyRateLimit(oxy, options = {}) {
|
|
161
|
+
const { authenticatedMax = 5000, anonymousMax = 600, windowMs = 15 * 60 * 1000, store, exempt, message = 'Too many requests, please try again later.', auth, } = options;
|
|
162
|
+
// Idempotent optional-auth resolver. Reuses the SAME session resolution as
|
|
163
|
+
// every protected route, so the limiter keys by the real user identity.
|
|
164
|
+
//
|
|
165
|
+
// `createOptionalOxyAuth` — NOT the raw `oxy.auth({ optional: true })` —
|
|
166
|
+
// because only the former skips resolution when a preceding middleware has
|
|
167
|
+
// already resolved a user. The raw middleware writes `req.userId = null` on
|
|
168
|
+
// every request it cannot authenticate, and because it mutates the shared
|
|
169
|
+
// `req` that erasure is visible to every handler downstream of the limiter,
|
|
170
|
+
// not just to the bucket calculation.
|
|
171
|
+
const resolveSession = (0, auth_1.createOptionalOxyAuth)(oxy, { auth });
|
|
172
|
+
const skip = (req) => isBuiltInExempt(req) || (exempt ? exempt(req) : false);
|
|
173
|
+
const limiter = (0, express_rate_limit_1.default)({
|
|
174
|
+
windowMs,
|
|
175
|
+
...(store ? { store } : {}),
|
|
176
|
+
max: (req) => {
|
|
177
|
+
return resolveTrustedAuthenticatedKey(req)
|
|
178
|
+
? authenticatedMax
|
|
179
|
+
: anonymousMax;
|
|
180
|
+
},
|
|
181
|
+
keyGenerator: (req) => resolveKey(req),
|
|
182
|
+
message,
|
|
183
|
+
standardHeaders: true,
|
|
184
|
+
legacyHeaders: false,
|
|
185
|
+
skip,
|
|
186
|
+
// hashAnonymousIp already buckets IPv6 to /56 before HMAC; disable the v8
|
|
187
|
+
// static source scan that false-positives on req.ip (ERR_ERL_KEY_GEN_IPV6).
|
|
188
|
+
validate: { keyGeneratorIpFallback: false },
|
|
189
|
+
});
|
|
190
|
+
return (req, res, next) => {
|
|
191
|
+
// Skipped paths bypass BOTH session resolution and limiting — cheap and
|
|
192
|
+
// safe for static/streaming/health traffic.
|
|
193
|
+
if (skip(req)) {
|
|
194
|
+
next();
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
resolveSession(req, res, (err) => {
|
|
198
|
+
if (err) {
|
|
199
|
+
// Optional auth never rejects; a token error just means "anonymous".
|
|
200
|
+
// Swallow the error and continue through the anonymous limiter.
|
|
201
|
+
limiter(req, res, next);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
limiter(req, res, next);
|
|
205
|
+
});
|
|
206
|
+
};
|
|
207
|
+
}
|