@oxyhq/services 5.17.17 → 5.17.18
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/README.md +32 -38
- package/lib/commonjs/core/CrossDomainAuth.js +277 -0
- package/lib/commonjs/core/CrossDomainAuth.js.map +1 -0
- package/lib/commonjs/core/HttpService.js +82 -15
- package/lib/commonjs/core/HttpService.js.map +1 -1
- package/lib/commonjs/core/OxyServices.base.js +11 -3
- package/lib/commonjs/core/OxyServices.base.js.map +1 -1
- package/lib/commonjs/core/OxyServices.js +4 -1
- package/lib/commonjs/core/OxyServices.js.map +1 -1
- package/lib/commonjs/core/index.js +30 -0
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/core/mixins/OxyServices.assets.js +16 -3
- package/lib/commonjs/core/mixins/OxyServices.assets.js.map +1 -1
- package/lib/commonjs/core/mixins/OxyServices.auth.js +73 -32
- package/lib/commonjs/core/mixins/OxyServices.auth.js.map +1 -1
- package/lib/commonjs/core/mixins/OxyServices.fedcm.js +289 -0
- package/lib/commonjs/core/mixins/OxyServices.fedcm.js.map +1 -0
- package/lib/commonjs/core/mixins/OxyServices.popup.js +352 -0
- package/lib/commonjs/core/mixins/OxyServices.popup.js.map +1 -0
- package/lib/commonjs/core/mixins/OxyServices.redirect.js +378 -0
- package/lib/commonjs/core/mixins/OxyServices.redirect.js.map +1 -0
- package/lib/commonjs/core/mixins/OxyServices.user.js +35 -24
- package/lib/commonjs/core/mixins/OxyServices.user.js.map +1 -1
- package/lib/commonjs/core/mixins/index.js +27 -15
- package/lib/commonjs/core/mixins/index.js.map +1 -1
- package/lib/commonjs/crypto/index.js +30 -0
- package/lib/commonjs/crypto/index.js.map +1 -1
- package/lib/commonjs/crypto/keyManager.js +902 -0
- package/lib/commonjs/crypto/keyManager.js.map +1 -0
- package/lib/commonjs/crypto/polyfill.js +14 -5
- package/lib/commonjs/crypto/polyfill.js.map +1 -1
- package/lib/commonjs/crypto/recoveryPhrase.js +152 -0
- package/lib/commonjs/crypto/recoveryPhrase.js.map +1 -0
- package/lib/commonjs/crypto/signatureService.js +289 -0
- package/lib/commonjs/crypto/signatureService.js.map +1 -0
- package/lib/commonjs/i18n/locales/en-US.json +1 -1
- package/lib/commonjs/index.js +40 -26
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/interfaces.js +0 -15
- package/lib/commonjs/models/interfaces.js.map +1 -1
- package/lib/commonjs/ui/components/BottomSheetRouter.js +9 -1
- package/lib/commonjs/ui/components/BottomSheetRouter.js.map +1 -1
- package/lib/commonjs/ui/components/Icon.js.map +1 -1
- package/lib/commonjs/ui/components/IconButton/utils.js.map +1 -1
- package/lib/commonjs/ui/components/OxyProvider.js +41 -11
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/TextField/Adornment/utils.js.map +1 -1
- package/lib/commonjs/ui/components/TextField/helpers.js.map +1 -1
- package/lib/commonjs/ui/components/TouchableRipple/utils.js.map +1 -1
- package/lib/commonjs/ui/components/Typography/AnimatedText.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +110 -199
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +150 -19
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useSessionManagement.js +279 -0
- package/lib/commonjs/ui/context/hooks/useSessionManagement.js.map +1 -0
- package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +79 -72
- package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +38 -51
- package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/useSecurityQueries.js +3 -3
- package/lib/commonjs/ui/hooks/queries/useSecurityQueries.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/useServicesQueries.js +18 -12
- package/lib/commonjs/ui/hooks/queries/useServicesQueries.js.map +1 -1
- package/lib/commonjs/ui/hooks/useProfileEditing.js +3 -5
- package/lib/commonjs/ui/hooks/useProfileEditing.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionManagement.js +4 -8
- package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionSocket.js +162 -315
- package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/commonjs/ui/hooks/useStorage.js +24 -58
- package/lib/commonjs/ui/hooks/useStorage.js.map +1 -1
- package/lib/commonjs/ui/index.js +50 -21
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/commonjs/ui/navigation/routes.js +5 -1
- package/lib/commonjs/ui/navigation/routes.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountCenterScreen.js +2 -2
- package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +29 -24
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +3 -3
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/OxyAuthScreen.js +134 -66
- package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PrivacySettingsScreen.js +6 -13
- package/lib/commonjs/ui/screens/PrivacySettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/stores/accountStore.js +2 -4
- package/lib/commonjs/ui/stores/accountStore.js.map +1 -1
- package/lib/commonjs/ui/stores/authStore.js +45 -32
- package/lib/commonjs/ui/stores/authStore.js.map +1 -1
- package/lib/commonjs/ui/styles/spacing.js +54 -2
- package/lib/commonjs/ui/styles/spacing.js.map +1 -1
- package/lib/commonjs/ui/utils/avatarUtils.js +37 -41
- package/lib/commonjs/ui/utils/avatarUtils.js.map +1 -1
- package/lib/commonjs/ui/utils/storageHelpers.js.map +1 -1
- package/lib/commonjs/utils/errorUtils.js +13 -0
- package/lib/commonjs/utils/errorUtils.js.map +1 -1
- package/lib/commonjs/utils/validationUtils.js +15 -1
- package/lib/commonjs/utils/validationUtils.js.map +1 -1
- package/lib/module/core/CrossDomainAuth.js +271 -0
- package/lib/module/core/CrossDomainAuth.js.map +1 -0
- package/lib/module/core/HttpService.js +82 -15
- package/lib/module/core/HttpService.js.map +1 -1
- package/lib/module/core/OxyServices.base.js +11 -4
- package/lib/module/core/OxyServices.base.js.map +1 -1
- package/lib/module/core/OxyServices.js +4 -1
- package/lib/module/core/OxyServices.js.map +1 -1
- package/lib/module/core/index.js +6 -1
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/core/mixins/OxyServices.assets.js +16 -3
- package/lib/module/core/mixins/OxyServices.assets.js.map +1 -1
- package/lib/module/core/mixins/OxyServices.auth.js +73 -32
- package/lib/module/core/mixins/OxyServices.auth.js.map +1 -1
- package/lib/module/core/mixins/OxyServices.fedcm.js +286 -0
- package/lib/module/core/mixins/OxyServices.fedcm.js.map +1 -0
- package/lib/module/core/mixins/OxyServices.popup.js +349 -0
- package/lib/module/core/mixins/OxyServices.popup.js.map +1 -0
- package/lib/module/core/mixins/OxyServices.redirect.js +375 -0
- package/lib/module/core/mixins/OxyServices.redirect.js.map +1 -0
- package/lib/module/core/mixins/OxyServices.user.js +35 -24
- package/lib/module/core/mixins/OxyServices.user.js.map +1 -1
- package/lib/module/core/mixins/index.js +15 -3
- package/lib/module/core/mixins/index.js.map +1 -1
- package/lib/module/crypto/index.js +8 -4
- package/lib/module/crypto/index.js.map +1 -1
- package/lib/module/crypto/keyManager.js +899 -0
- package/lib/module/crypto/keyManager.js.map +1 -0
- package/lib/module/crypto/polyfill.js +6 -5
- package/lib/module/crypto/polyfill.js.map +1 -1
- package/lib/module/crypto/recoveryPhrase.js +147 -0
- package/lib/module/crypto/recoveryPhrase.js.map +1 -0
- package/lib/module/crypto/signatureService.js +286 -0
- package/lib/module/crypto/signatureService.js.map +1 -0
- package/lib/module/i18n/locales/en-US.json +1 -1
- package/lib/module/index.js +6 -9
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/interfaces.js +0 -15
- package/lib/module/models/interfaces.js.map +1 -1
- package/lib/module/ui/components/BottomSheetRouter.js +6 -2
- package/lib/module/ui/components/BottomSheetRouter.js.map +1 -1
- package/lib/module/ui/components/Icon.js.map +1 -1
- package/lib/module/ui/components/IconButton/utils.js.map +1 -1
- package/lib/module/ui/components/OxyProvider.js +41 -11
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/TextField/Adornment/utils.js.map +1 -1
- package/lib/module/ui/components/TextField/helpers.js.map +1 -1
- package/lib/module/ui/components/TouchableRipple/utils.js.map +1 -1
- package/lib/module/ui/components/Typography/AnimatedText.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +112 -191
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +150 -19
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/context/hooks/useSessionManagement.js +274 -0
- package/lib/module/ui/context/hooks/useSessionManagement.js.map +1 -0
- package/lib/module/ui/hooks/mutations/useAccountMutations.js +80 -72
- package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
- package/lib/module/ui/hooks/queries/useAccountQueries.js +31 -44
- package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
- package/lib/module/ui/hooks/queries/useSecurityQueries.js +1 -1
- package/lib/module/ui/hooks/queries/useSecurityQueries.js.map +1 -1
- package/lib/module/ui/hooks/queries/useServicesQueries.js +13 -7
- package/lib/module/ui/hooks/queries/useServicesQueries.js.map +1 -1
- package/lib/module/ui/hooks/useProfileEditing.js +3 -5
- package/lib/module/ui/hooks/useProfileEditing.js.map +1 -1
- package/lib/module/ui/hooks/useSessionManagement.js +4 -8
- package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/module/ui/hooks/useSessionSocket.js +162 -315
- package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/module/ui/hooks/useStorage.js +25 -59
- package/lib/module/ui/hooks/useStorage.js.map +1 -1
- package/lib/module/ui/index.js +15 -10
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/navigation/routes.js +5 -1
- package/lib/module/ui/navigation/routes.js.map +1 -1
- package/lib/module/ui/screens/AccountCenterScreen.js +2 -2
- package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +29 -24
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +3 -3
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/OxyAuthScreen.js +135 -68
- package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/module/ui/screens/PrivacySettingsScreen.js +6 -13
- package/lib/module/ui/screens/PrivacySettingsScreen.js.map +1 -1
- package/lib/module/ui/stores/accountStore.js +2 -4
- package/lib/module/ui/stores/accountStore.js.map +1 -1
- package/lib/module/ui/stores/authStore.js +45 -32
- package/lib/module/ui/stores/authStore.js.map +1 -1
- package/lib/module/ui/styles/spacing.js +6 -2
- package/lib/module/ui/styles/spacing.js.map +1 -1
- package/lib/module/ui/utils/avatarUtils.js +37 -40
- package/lib/module/ui/utils/avatarUtils.js.map +1 -1
- package/lib/module/ui/utils/storageHelpers.js.map +1 -1
- package/lib/module/utils/errorUtils.js +7 -0
- package/lib/module/utils/errorUtils.js.map +1 -1
- package/lib/module/utils/validationUtils.js +13 -0
- package/lib/module/utils/validationUtils.js.map +1 -1
- package/lib/typescript/core/CrossDomainAuth.d.ts +161 -0
- package/lib/typescript/core/CrossDomainAuth.d.ts.map +1 -0
- package/lib/typescript/core/HttpService.d.ts +1 -1
- package/lib/typescript/core/HttpService.d.ts.map +1 -1
- package/lib/typescript/core/OxyServices.base.d.ts +0 -6
- package/lib/typescript/core/OxyServices.base.d.ts.map +1 -1
- package/lib/typescript/core/OxyServices.d.ts +5 -36
- package/lib/typescript/core/OxyServices.d.ts.map +1 -1
- package/lib/typescript/core/index.d.ts +4 -0
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.analytics.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.assets.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.auth.d.ts +40 -20
- package/lib/typescript/core/mixins/OxyServices.auth.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.developer.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.devices.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.fedcm.d.ts +195 -0
- package/lib/typescript/core/mixins/OxyServices.fedcm.d.ts.map +1 -0
- package/lib/typescript/core/mixins/OxyServices.karma.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.language.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.location.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.payment.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.popup.d.ts +206 -0
- package/lib/typescript/core/mixins/OxyServices.popup.d.ts.map +1 -0
- package/lib/typescript/core/mixins/OxyServices.privacy.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.redirect.d.ts +246 -0
- package/lib/typescript/core/mixins/OxyServices.redirect.d.ts.map +1 -0
- package/lib/typescript/core/mixins/OxyServices.security.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.user.d.ts +6 -4
- package/lib/typescript/core/mixins/OxyServices.user.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.utility.d.ts.map +1 -1
- package/lib/typescript/core/mixins/index.d.ts +220 -8
- package/lib/typescript/core/mixins/index.d.ts.map +1 -1
- package/lib/typescript/crypto/index.d.ts +6 -3
- package/lib/typescript/crypto/index.d.ts.map +1 -1
- package/lib/typescript/crypto/keyManager.d.ts +190 -0
- package/lib/typescript/crypto/keyManager.d.ts.map +1 -0
- package/lib/typescript/crypto/polyfill.d.ts +4 -3
- package/lib/typescript/crypto/polyfill.d.ts.map +1 -1
- package/lib/typescript/crypto/recoveryPhrase.d.ts +59 -0
- package/lib/typescript/crypto/recoveryPhrase.d.ts.map +1 -0
- package/lib/typescript/crypto/signatureService.d.ts +87 -0
- package/lib/typescript/crypto/signatureService.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +5 -6
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/models/interfaces.d.ts +2 -14
- package/lib/typescript/models/interfaces.d.ts.map +1 -1
- package/lib/typescript/models/session.d.ts +0 -9
- package/lib/typescript/models/session.d.ts.map +1 -1
- package/lib/typescript/types/bip39.d.ts +32 -0
- package/lib/typescript/ui/components/BottomSheetRouter.d.ts +5 -0
- package/lib/typescript/ui/components/BottomSheetRouter.d.ts.map +1 -1
- package/lib/typescript/ui/components/IconButton/utils.d.ts +1 -1
- package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/ui/components/TextField/Addons/Outline.d.ts +2 -2
- package/lib/typescript/ui/components/TextField/Adornment/utils.d.ts +1 -1
- package/lib/typescript/ui/components/TextField/Adornment/utils.d.ts.map +1 -1
- package/lib/typescript/ui/components/TextField/helpers.d.ts +8 -8
- package/lib/typescript/ui/components/TextField/types.d.ts +1 -0
- package/lib/typescript/ui/components/TextField/types.d.ts.map +1 -1
- package/lib/typescript/ui/components/types.d.ts +4 -0
- package/lib/typescript/ui/components/types.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts +57 -3
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts +10 -3
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useSessionManagement.d.ts +41 -0
- package/lib/typescript/ui/context/hooks/useSessionManagement.d.ts.map +1 -0
- package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useProfileEditing.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useSessionSocket.d.ts +1 -2
- package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useStorage.d.ts +3 -9
- package/lib/typescript/ui/hooks/useStorage.d.ts.map +1 -1
- package/lib/typescript/ui/index.d.ts +6 -2
- package/lib/typescript/ui/index.d.ts.map +1 -1
- package/lib/typescript/ui/navigation/routes.d.ts +1 -1
- package/lib/typescript/ui/navigation/routes.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/OxyAuthScreen.d.ts +1 -1
- package/lib/typescript/ui/screens/OxyAuthScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/PrivacySettingsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/stores/accountStore.d.ts.map +1 -1
- package/lib/typescript/ui/stores/authStore.d.ts +8 -7
- package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
- package/lib/typescript/ui/styles/spacing.d.ts +5 -0
- package/lib/typescript/ui/styles/spacing.d.ts.map +1 -1
- package/lib/typescript/ui/types/navigation.d.ts +2 -1
- package/lib/typescript/ui/types/navigation.d.ts.map +1 -1
- package/lib/typescript/ui/utils/avatarUtils.d.ts +2 -13
- package/lib/typescript/ui/utils/avatarUtils.d.ts.map +1 -1
- package/lib/typescript/ui/utils/storageHelpers.d.ts +0 -3
- package/lib/typescript/ui/utils/storageHelpers.d.ts.map +1 -1
- package/lib/typescript/utils/errorUtils.d.ts +6 -0
- package/lib/typescript/utils/errorUtils.d.ts.map +1 -1
- package/lib/typescript/utils/validationUtils.d.ts +8 -0
- package/lib/typescript/utils/validationUtils.d.ts.map +1 -1
- package/package.json +8 -7
- package/src/core/CrossDomainAuth.ts +307 -0
- package/src/core/HttpService.ts +99 -16
- package/src/core/OxyServices.base.ts +20 -3
- package/src/core/OxyServices.ts +7 -3
- package/src/core/index.ts +9 -1
- package/src/core/mixins/OxyServices.assets.ts +14 -3
- package/src/core/mixins/OxyServices.auth.ts +105 -36
- package/src/core/mixins/OxyServices.fedcm.ts +315 -0
- package/src/core/mixins/OxyServices.popup.ts +402 -0
- package/src/core/mixins/OxyServices.redirect.ts +397 -0
- package/src/core/mixins/OxyServices.user.ts +39 -24
- package/src/core/mixins/index.ts +19 -3
- package/src/crypto/index.ts +16 -5
- package/src/crypto/keyManager.ts +966 -0
- package/src/crypto/polyfill.ts +6 -5
- package/src/crypto/recoveryPhrase.ts +166 -0
- package/src/crypto/signatureService.ts +323 -0
- package/src/i18n/locales/en-US.json +1 -1
- package/src/index.ts +19 -15
- package/src/models/interfaces.ts +4 -16
- package/src/models/session.ts +2 -11
- package/src/types/bip39.d.ts +32 -0
- package/src/ui/components/BottomSheetRouter.tsx +6 -1
- package/src/ui/components/Icon.tsx +1 -1
- package/src/ui/components/IconButton/utils.ts +1 -1
- package/src/ui/components/OxyProvider.tsx +44 -12
- package/src/ui/components/TextField/Addons/Outline.tsx +2 -2
- package/src/ui/components/TextField/Adornment/utils.ts +2 -2
- package/src/ui/components/TextField/helpers.tsx +10 -10
- package/src/ui/components/TextField/types.tsx +1 -1
- package/src/ui/components/TouchableRipple/utils.ts +2 -2
- package/src/ui/components/Typography/AnimatedText.tsx +2 -2
- package/src/ui/components/types.tsx +6 -0
- package/src/ui/context/OxyContext.tsx +173 -195
- package/src/ui/context/hooks/useAuthOperations.ts +177 -36
- package/src/ui/context/hooks/useSessionManagement.ts +399 -0
- package/src/ui/hooks/mutations/useAccountMutations.ts +83 -76
- package/src/ui/hooks/queries/useAccountQueries.ts +29 -35
- package/src/ui/hooks/queries/useSecurityQueries.ts +1 -1
- package/src/ui/hooks/queries/useServicesQueries.ts +14 -6
- package/src/ui/hooks/useProfileEditing.ts +3 -3
- package/src/ui/hooks/useSessionManagement.ts +5 -10
- package/src/ui/hooks/useSessionSocket.ts +46 -175
- package/src/ui/hooks/useStorage.ts +24 -76
- package/src/ui/index.ts +22 -13
- package/src/ui/navigation/routes.ts +6 -2
- package/src/ui/screens/AccountCenterScreen.tsx +2 -2
- package/src/ui/screens/AccountOverviewScreen.tsx +1 -1
- package/src/ui/screens/AccountSettingsScreen.tsx +34 -37
- package/src/ui/screens/AccountSwitcherScreen.tsx +4 -4
- package/src/ui/screens/OxyAuthScreen.tsx +138 -64
- package/src/ui/screens/PrivacySettingsScreen.tsx +6 -12
- package/src/ui/stores/accountStore.ts +1 -11
- package/src/ui/stores/authStore.ts +43 -44
- package/src/ui/styles/spacing.ts +15 -2
- package/src/ui/types/navigation.ts +2 -2
- package/src/ui/utils/avatarUtils.ts +39 -46
- package/src/ui/utils/storageHelpers.ts +0 -4
- package/src/utils/__tests__/validationUtils.test.ts +16 -1
- package/src/utils/errorUtils.ts +8 -1
- package/src/utils/validationUtils.ts +12 -0
- package/lib/commonjs/core/services/SessionService.js +0 -163
- package/lib/commonjs/core/services/SessionService.js.map +0 -1
- package/lib/commonjs/core/services/TokenService.js +0 -220
- package/lib/commonjs/core/services/TokenService.js.map +0 -1
- package/lib/commonjs/crypto/types.js +0 -2
- package/lib/commonjs/crypto/types.js.map +0 -1
- package/lib/commonjs/ui/context/OxyContextBase.js +0 -21
- package/lib/commonjs/ui/context/OxyContextBase.js.map +0 -1
- package/lib/commonjs/ui/context/hooks/useStorage.js +0 -79
- package/lib/commonjs/ui/context/hooks/useStorage.js.map +0 -1
- package/lib/commonjs/ui/hooks/useAvatarPicker.js +0 -56
- package/lib/commonjs/ui/hooks/useAvatarPicker.js.map +0 -1
- package/lib/module/core/services/SessionService.js +0 -159
- package/lib/module/core/services/SessionService.js.map +0 -1
- package/lib/module/core/services/TokenService.js +0 -217
- package/lib/module/core/services/TokenService.js.map +0 -1
- package/lib/module/crypto/types.js +0 -2
- package/lib/module/crypto/types.js.map +0 -1
- package/lib/module/ui/context/OxyContextBase.js +0 -16
- package/lib/module/ui/context/OxyContextBase.js.map +0 -1
- package/lib/module/ui/context/hooks/useStorage.js +0 -74
- package/lib/module/ui/context/hooks/useStorage.js.map +0 -1
- package/lib/module/ui/hooks/useAvatarPicker.js +0 -50
- package/lib/module/ui/hooks/useAvatarPicker.js.map +0 -1
- package/lib/typescript/core/services/SessionService.d.ts +0 -78
- package/lib/typescript/core/services/SessionService.d.ts.map +0 -1
- package/lib/typescript/core/services/TokenService.d.ts +0 -72
- package/lib/typescript/core/services/TokenService.d.ts.map +0 -1
- package/lib/typescript/crypto/types.d.ts +0 -22
- package/lib/typescript/crypto/types.d.ts.map +0 -1
- package/lib/typescript/ui/context/OxyContextBase.d.ts +0 -63
- package/lib/typescript/ui/context/OxyContextBase.d.ts.map +0 -1
- package/lib/typescript/ui/context/hooks/useStorage.d.ts +0 -22
- package/lib/typescript/ui/context/hooks/useStorage.d.ts.map +0 -1
- package/lib/typescript/ui/hooks/useAvatarPicker.d.ts +0 -19
- package/lib/typescript/ui/hooks/useAvatarPicker.d.ts.map +0 -1
- package/src/core/services/SessionService.ts +0 -173
- package/src/core/services/TokenService.ts +0 -237
- package/src/crypto/types.ts +0 -23
- package/src/ui/context/OxyContextBase.tsx +0 -78
- package/src/ui/context/hooks/useStorage.ts +0 -104
- package/src/ui/hooks/useAvatarPicker.ts +0 -61
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Authentication Methods Mixin
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* No passwords required - authentication is done via challenge-response.
|
|
4
|
+
* Supports password-based login (email/username) and public key challenge-response.
|
|
6
5
|
*/
|
|
7
6
|
import type { User } from '../../models/interfaces';
|
|
8
7
|
import type { SessionLoginResponse } from '../../models/session';
|
|
@@ -14,6 +13,23 @@ export interface ChallengeResponse {
|
|
|
14
13
|
expiresAt: string;
|
|
15
14
|
}
|
|
16
15
|
|
|
16
|
+
export interface RegistrationRequest {
|
|
17
|
+
publicKey: string;
|
|
18
|
+
username: string;
|
|
19
|
+
email?: string;
|
|
20
|
+
signature: string;
|
|
21
|
+
timestamp: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ChallengeVerifyRequest {
|
|
25
|
+
publicKey: string;
|
|
26
|
+
challenge: string;
|
|
27
|
+
signature: string;
|
|
28
|
+
timestamp: number;
|
|
29
|
+
deviceName?: string;
|
|
30
|
+
deviceFingerprint?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
17
33
|
export interface PublicKeyCheckResponse {
|
|
18
34
|
registered: boolean;
|
|
19
35
|
message: string;
|
|
@@ -26,21 +42,26 @@ export function OxyServicesAuthMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
26
42
|
}
|
|
27
43
|
|
|
28
44
|
/**
|
|
29
|
-
* Register a new identity
|
|
30
|
-
*
|
|
31
|
-
* Register a new identity (public key only).
|
|
32
|
-
* Profile data should be synced separately via updateProfile after sign-in.
|
|
45
|
+
* Register a new identity with public key authentication
|
|
46
|
+
* Identity is purely cryptographic - username and profile data are optional
|
|
33
47
|
*
|
|
34
48
|
* @param publicKey - The user's ECDSA public key (hex)
|
|
35
|
-
* @
|
|
49
|
+
* @param signature - Signature of the registration request
|
|
50
|
+
* @param timestamp - Timestamp when the signature was created
|
|
36
51
|
*/
|
|
37
|
-
async
|
|
52
|
+
async register(
|
|
53
|
+
publicKey: string,
|
|
54
|
+
signature: string,
|
|
55
|
+
timestamp: number
|
|
56
|
+
): Promise<{ message: string; user: User }> {
|
|
38
57
|
try {
|
|
39
|
-
const res = await this.makeRequest<{
|
|
58
|
+
const res = await this.makeRequest<{ message: string; user: User }>('POST', '/api/auth/register', {
|
|
40
59
|
publicKey,
|
|
60
|
+
signature,
|
|
61
|
+
timestamp,
|
|
41
62
|
}, { cache: false });
|
|
42
63
|
|
|
43
|
-
if (!res ||
|
|
64
|
+
if (!res || (typeof res === 'object' && Object.keys(res).length === 0)) {
|
|
44
65
|
throw new OxyAuthenticationError('Registration failed', 'REGISTER_FAILED', 400);
|
|
45
66
|
}
|
|
46
67
|
|
|
@@ -54,12 +75,12 @@ export function OxyServicesAuthMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
54
75
|
* Request an authentication challenge
|
|
55
76
|
* The client must sign this challenge with their private key
|
|
56
77
|
*
|
|
57
|
-
* @param
|
|
78
|
+
* @param publicKey - The user's public key
|
|
58
79
|
*/
|
|
59
|
-
async requestChallenge(
|
|
80
|
+
async requestChallenge(publicKey: string): Promise<ChallengeResponse> {
|
|
60
81
|
try {
|
|
61
82
|
return await this.makeRequest<ChallengeResponse>('POST', '/api/auth/challenge', {
|
|
62
|
-
|
|
83
|
+
publicKey,
|
|
63
84
|
}, { cache: false });
|
|
64
85
|
} catch (error) {
|
|
65
86
|
throw this.handleError(error);
|
|
@@ -69,16 +90,16 @@ export function OxyServicesAuthMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
69
90
|
/**
|
|
70
91
|
* Verify a signed challenge and create a session
|
|
71
92
|
*
|
|
72
|
-
* @param
|
|
73
|
-
* @param
|
|
93
|
+
* @param publicKey - The user's public key
|
|
94
|
+
* @param challenge - The challenge string from requestChallenge
|
|
74
95
|
* @param signature - Signature of the auth message
|
|
75
96
|
* @param timestamp - Timestamp when the signature was created
|
|
76
97
|
* @param deviceName - Optional device name
|
|
77
98
|
* @param deviceFingerprint - Optional device fingerprint
|
|
78
99
|
*/
|
|
79
100
|
async verifyChallenge(
|
|
80
|
-
|
|
81
|
-
|
|
101
|
+
publicKey: string,
|
|
102
|
+
challenge: string,
|
|
82
103
|
signature: string,
|
|
83
104
|
timestamp: number,
|
|
84
105
|
deviceName?: string,
|
|
@@ -86,8 +107,8 @@ export function OxyServicesAuthMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
86
107
|
): Promise<SessionLoginResponse> {
|
|
87
108
|
try {
|
|
88
109
|
return await this.makeRequest<SessionLoginResponse>('POST', '/api/auth/verify', {
|
|
89
|
-
|
|
90
|
-
|
|
110
|
+
publicKey,
|
|
111
|
+
challenge,
|
|
91
112
|
signature,
|
|
92
113
|
timestamp,
|
|
93
114
|
deviceName,
|
|
@@ -116,7 +137,6 @@ export function OxyServicesAuthMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
116
137
|
|
|
117
138
|
/**
|
|
118
139
|
* Get user by public key
|
|
119
|
-
* Services never caches profile - always fetch fresh from backend
|
|
120
140
|
*/
|
|
121
141
|
async getUserByPublicKey(publicKey: string): Promise<User> {
|
|
122
142
|
try {
|
|
@@ -124,7 +144,7 @@ export function OxyServicesAuthMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
124
144
|
'GET',
|
|
125
145
|
`/api/auth/user/${encodeURIComponent(publicKey)}`,
|
|
126
146
|
undefined,
|
|
127
|
-
{ cache:
|
|
147
|
+
{ cache: true, cacheTTL: 2 * 60 * 1000 }
|
|
128
148
|
);
|
|
129
149
|
} catch (error) {
|
|
130
150
|
throw this.handleError(error);
|
|
@@ -133,12 +153,12 @@ export function OxyServicesAuthMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
133
153
|
|
|
134
154
|
/**
|
|
135
155
|
* Get user by session ID
|
|
136
|
-
* Services never caches profile - always fetch fresh from backend
|
|
137
156
|
*/
|
|
138
157
|
async getUserBySession(sessionId: string): Promise<User> {
|
|
139
158
|
try {
|
|
140
159
|
return await this.makeRequest<User>('GET', `/api/session/user/${sessionId}`, undefined, {
|
|
141
|
-
cache:
|
|
160
|
+
cache: true,
|
|
161
|
+
cacheTTL: 2 * 60 * 1000,
|
|
142
162
|
});
|
|
143
163
|
} catch (error) {
|
|
144
164
|
throw this.handleError(error);
|
|
@@ -161,7 +181,8 @@ export function OxyServicesAuthMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
161
181
|
'/api/session/users/batch',
|
|
162
182
|
{ sessionIds: uniqueSessionIds },
|
|
163
183
|
{
|
|
164
|
-
cache:
|
|
184
|
+
cache: true,
|
|
185
|
+
cacheTTL: 2 * 60 * 1000,
|
|
165
186
|
deduplicate: true,
|
|
166
187
|
}
|
|
167
188
|
);
|
|
@@ -173,23 +194,16 @@ export function OxyServicesAuthMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
173
194
|
/**
|
|
174
195
|
* Get access token by session ID
|
|
175
196
|
*/
|
|
176
|
-
async getTokenBySession(
|
|
177
|
-
sessionId: string,
|
|
178
|
-
deviceId?: string
|
|
179
|
-
): Promise<{ accessToken: string; refreshToken: string; expiresAt: string; sessionId: string; deviceId: string }> {
|
|
197
|
+
async getTokenBySession(sessionId: string): Promise<{ accessToken: string; expiresAt: string }> {
|
|
180
198
|
try {
|
|
181
|
-
const res = await this.makeRequest<{ accessToken: string;
|
|
199
|
+
const res = await this.makeRequest<{ accessToken: string; expiresAt: string }>(
|
|
182
200
|
'GET',
|
|
183
201
|
`/api/session/token/${sessionId}`,
|
|
184
202
|
undefined,
|
|
185
|
-
{
|
|
186
|
-
cache: false,
|
|
187
|
-
retry: false,
|
|
188
|
-
headers: deviceId ? { 'x-device-id': deviceId } : undefined,
|
|
189
|
-
}
|
|
203
|
+
{ cache: false, retry: false }
|
|
190
204
|
);
|
|
191
|
-
|
|
192
|
-
this.setTokens(res.accessToken
|
|
205
|
+
|
|
206
|
+
this.setTokens(res.accessToken);
|
|
193
207
|
|
|
194
208
|
return res;
|
|
195
209
|
} catch (error) {
|
|
@@ -285,5 +299,60 @@ export function OxyServicesAuthMixin<T extends typeof OxyServicesBase>(Base: T)
|
|
|
285
299
|
}
|
|
286
300
|
}
|
|
287
301
|
|
|
302
|
+
/**
|
|
303
|
+
* Register a new user with email/username and password
|
|
304
|
+
*/
|
|
305
|
+
async signUp(
|
|
306
|
+
username: string,
|
|
307
|
+
email: string,
|
|
308
|
+
password: string,
|
|
309
|
+
deviceName?: string,
|
|
310
|
+
deviceFingerprint?: any
|
|
311
|
+
): Promise<SessionLoginResponse> {
|
|
312
|
+
try {
|
|
313
|
+
return await this.makeRequest<SessionLoginResponse>('POST', '/api/auth/signup', {
|
|
314
|
+
username,
|
|
315
|
+
email,
|
|
316
|
+
password,
|
|
317
|
+
deviceName,
|
|
318
|
+
deviceFingerprint,
|
|
319
|
+
}, { cache: false });
|
|
320
|
+
} catch (error) {
|
|
321
|
+
throw this.handleError(error);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Sign in with email or username and password
|
|
327
|
+
*/
|
|
328
|
+
async signIn(
|
|
329
|
+
identifier: string,
|
|
330
|
+
password: string,
|
|
331
|
+
deviceName?: string,
|
|
332
|
+
deviceFingerprint?: any
|
|
333
|
+
): Promise<SessionLoginResponse> {
|
|
334
|
+
try {
|
|
335
|
+
return await this.makeRequest<SessionLoginResponse>('POST', '/api/auth/login', {
|
|
336
|
+
identifier,
|
|
337
|
+
password,
|
|
338
|
+
deviceName,
|
|
339
|
+
deviceFingerprint,
|
|
340
|
+
}, { cache: false });
|
|
341
|
+
} catch (error) {
|
|
342
|
+
throw this.handleError(error);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Convenience helper for email sign-in
|
|
348
|
+
*/
|
|
349
|
+
async signInWithEmail(
|
|
350
|
+
email: string,
|
|
351
|
+
password: string,
|
|
352
|
+
deviceName?: string,
|
|
353
|
+
deviceFingerprint?: any
|
|
354
|
+
): Promise<SessionLoginResponse> {
|
|
355
|
+
return this.signIn(email, password, deviceName, deviceFingerprint);
|
|
356
|
+
}
|
|
288
357
|
};
|
|
289
358
|
}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import type { OxyServicesBase } from '../OxyServices.base';
|
|
2
|
+
import { OxyAuthenticationError } from '../OxyServices.errors';
|
|
3
|
+
import type { SessionLoginResponse } from '../../models/session';
|
|
4
|
+
|
|
5
|
+
export interface FedCMAuthOptions {
|
|
6
|
+
nonce?: string;
|
|
7
|
+
context?: 'signin' | 'signup' | 'continue' | 'use';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface FedCMConfig {
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
configURL: string;
|
|
13
|
+
clientId?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Federated Credential Management (FedCM) Authentication Mixin
|
|
18
|
+
*
|
|
19
|
+
* Implements the modern browser-native identity federation API that enables
|
|
20
|
+
* Google-style cross-domain authentication without third-party cookies.
|
|
21
|
+
*
|
|
22
|
+
* Browser Support:
|
|
23
|
+
* - Chrome 108+
|
|
24
|
+
* - Safari 16.4+
|
|
25
|
+
* - Edge 108+
|
|
26
|
+
* - Firefox: Not yet supported (fallback required)
|
|
27
|
+
*
|
|
28
|
+
* Key Features:
|
|
29
|
+
* - No redirects or popups required
|
|
30
|
+
* - Browser-native UI prompts
|
|
31
|
+
* - Privacy-preserving (IdP can't track users)
|
|
32
|
+
* - Automatic SSO across domains
|
|
33
|
+
* - Silent re-authentication support
|
|
34
|
+
*
|
|
35
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/FedCM_API
|
|
36
|
+
*/
|
|
37
|
+
export function OxyServicesFedCMMixin<T extends typeof OxyServicesBase>(Base: T) {
|
|
38
|
+
return class extends Base {
|
|
39
|
+
constructor(...args: any[]) {
|
|
40
|
+
super(...(args as [any]));
|
|
41
|
+
}
|
|
42
|
+
public static readonly DEFAULT_CONFIG_URL = 'https://auth.oxy.so/fedcm.json';
|
|
43
|
+
public static readonly FEDCM_TIMEOUT = 60000; // 1 minute
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Check if FedCM is supported in the current browser
|
|
47
|
+
*/
|
|
48
|
+
static isFedCMSupported(): boolean {
|
|
49
|
+
if (typeof window === 'undefined') return false;
|
|
50
|
+
return 'IdentityCredential' in window && 'navigator' in window && 'credentials' in navigator;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Instance method to check FedCM support
|
|
55
|
+
*/
|
|
56
|
+
isFedCMSupported(): boolean {
|
|
57
|
+
return (this.constructor as typeof OxyServicesBase & { isFedCMSupported: () => boolean }).isFedCMSupported();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Sign in using FedCM (Federated Credential Management API)
|
|
62
|
+
*
|
|
63
|
+
* This provides a Google-style authentication experience:
|
|
64
|
+
* - Browser shows native "Sign in with Oxy" prompt
|
|
65
|
+
* - No redirect or popup required
|
|
66
|
+
* - User approves → credential exchange happens in browser
|
|
67
|
+
* - All apps automatically get SSO after first sign-in
|
|
68
|
+
*
|
|
69
|
+
* @param options - Authentication options
|
|
70
|
+
* @returns Session with access token and user data
|
|
71
|
+
* @throws {OxyAuthenticationError} If FedCM not supported or user cancels
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* try {
|
|
76
|
+
* const session = await oxyServices.signInWithFedCM();
|
|
77
|
+
* console.log('Signed in:', session.user);
|
|
78
|
+
* } catch (error) {
|
|
79
|
+
* // Fallback to popup or redirect auth
|
|
80
|
+
* await oxyServices.signInWithPopup();
|
|
81
|
+
* }
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
async signInWithFedCM(options: FedCMAuthOptions = {}): Promise<SessionLoginResponse> {
|
|
85
|
+
if (!this.isFedCMSupported()) {
|
|
86
|
+
throw new OxyAuthenticationError(
|
|
87
|
+
'FedCM not supported in this browser. Please update your browser or use an alternative sign-in method.'
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
const nonce = options.nonce || this.generateNonce();
|
|
93
|
+
const clientId = this.getClientId();
|
|
94
|
+
|
|
95
|
+
// Request credential from browser's native identity flow
|
|
96
|
+
const credential = await this.requestIdentityCredential({
|
|
97
|
+
configURL: (this.constructor as any).DEFAULT_CONFIG_URL,
|
|
98
|
+
clientId,
|
|
99
|
+
nonce,
|
|
100
|
+
context: options.context,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (!credential || !credential.token) {
|
|
104
|
+
throw new OxyAuthenticationError('No credential received from browser');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Exchange FedCM ID token for Oxy session
|
|
108
|
+
const session = await this.exchangeIdTokenForSession(credential.token);
|
|
109
|
+
|
|
110
|
+
// Store access token in HttpService (extract from response or get from session)
|
|
111
|
+
if (session && (session as any).accessToken) {
|
|
112
|
+
this.httpService.setTokens((session as any).accessToken);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return session;
|
|
116
|
+
} catch (error) {
|
|
117
|
+
if ((error as any).name === 'AbortError') {
|
|
118
|
+
throw new OxyAuthenticationError('Sign-in was cancelled by user');
|
|
119
|
+
}
|
|
120
|
+
if ((error as any).name === 'NetworkError') {
|
|
121
|
+
throw new OxyAuthenticationError('Network error during sign-in. Please check your connection.');
|
|
122
|
+
}
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Silent sign-in using FedCM
|
|
129
|
+
*
|
|
130
|
+
* Attempts to automatically re-authenticate the user without any UI.
|
|
131
|
+
* This is what enables "instant sign-in" across all Oxy domains after
|
|
132
|
+
* the user has signed in once.
|
|
133
|
+
*
|
|
134
|
+
* The browser will:
|
|
135
|
+
* 1. Check if user has previously signed in to Oxy
|
|
136
|
+
* 2. Check if user is still signed in at auth.oxy.so
|
|
137
|
+
* 3. If yes, automatically provide credential without prompting
|
|
138
|
+
*
|
|
139
|
+
* @returns Session if user is already signed in, null otherwise
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* // On app startup
|
|
144
|
+
* useEffect(() => {
|
|
145
|
+
* const checkAuth = async () => {
|
|
146
|
+
* const session = await oxyServices.silentSignInWithFedCM();
|
|
147
|
+
* if (session) {
|
|
148
|
+
* setUser(session.user);
|
|
149
|
+
* } else {
|
|
150
|
+
* // Show sign-in button
|
|
151
|
+
* }
|
|
152
|
+
* };
|
|
153
|
+
* checkAuth();
|
|
154
|
+
* }, []);
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
async silentSignInWithFedCM(): Promise<SessionLoginResponse | null> {
|
|
158
|
+
if (!this.isFedCMSupported()) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
const nonce = this.generateNonce();
|
|
164
|
+
const clientId = this.getClientId();
|
|
165
|
+
|
|
166
|
+
// Request credential with silent mediation (no UI)
|
|
167
|
+
const credential = await this.requestIdentityCredential({
|
|
168
|
+
configURL: (this.constructor as any).DEFAULT_CONFIG_URL,
|
|
169
|
+
clientId,
|
|
170
|
+
nonce,
|
|
171
|
+
mediation: 'silent',
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
if (!credential || !credential.token) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const session = await this.exchangeIdTokenForSession(credential.token);
|
|
179
|
+
if (session && (session as any).accessToken) {
|
|
180
|
+
this.httpService.setTokens((session as any).accessToken);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return session;
|
|
184
|
+
} catch (error) {
|
|
185
|
+
// Silent failures are expected and should not throw
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Request identity credential from browser using FedCM API
|
|
192
|
+
*
|
|
193
|
+
* @private
|
|
194
|
+
*/
|
|
195
|
+
public async requestIdentityCredential(options: {
|
|
196
|
+
configURL: string;
|
|
197
|
+
clientId: string;
|
|
198
|
+
nonce: string;
|
|
199
|
+
context?: string;
|
|
200
|
+
mediation?: 'silent' | 'optional' | 'required';
|
|
201
|
+
}): Promise<{ token: string } | null> {
|
|
202
|
+
const controller = new AbortController();
|
|
203
|
+
const timeout = setTimeout(() => controller.abort(), (this.constructor as any).FEDCM_TIMEOUT);
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
// Type assertion needed as FedCM types may not be in all TypeScript versions
|
|
207
|
+
const credential = (await (navigator.credentials as any).get({
|
|
208
|
+
identity: {
|
|
209
|
+
providers: [
|
|
210
|
+
{
|
|
211
|
+
configURL: options.configURL,
|
|
212
|
+
clientId: options.clientId,
|
|
213
|
+
nonce: options.nonce,
|
|
214
|
+
...(options.context && { loginHint: options.context }),
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
},
|
|
218
|
+
mediation: options.mediation || 'optional',
|
|
219
|
+
signal: controller.signal,
|
|
220
|
+
})) as any;
|
|
221
|
+
|
|
222
|
+
if (!credential || credential.type !== 'identity') {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return { token: credential.token };
|
|
227
|
+
} finally {
|
|
228
|
+
clearTimeout(timeout);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Exchange FedCM ID token for Oxy session
|
|
234
|
+
*
|
|
235
|
+
* The ID token is a JWT issued by auth.oxy.so that proves the user's
|
|
236
|
+
* identity. We exchange it for a full Oxy session with access token.
|
|
237
|
+
*
|
|
238
|
+
* @private
|
|
239
|
+
*/
|
|
240
|
+
public async exchangeIdTokenForSession(idToken: string): Promise<SessionLoginResponse> {
|
|
241
|
+
return this.makeRequest<SessionLoginResponse>(
|
|
242
|
+
'POST',
|
|
243
|
+
'/api/auth/fedcm/exchange',
|
|
244
|
+
{ id_token: idToken },
|
|
245
|
+
{ cache: false }
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Revoke FedCM credential (sign out)
|
|
251
|
+
*
|
|
252
|
+
* This tells the browser to forget the FedCM credential for this app.
|
|
253
|
+
* The user will need to re-authenticate next time.
|
|
254
|
+
*/
|
|
255
|
+
async revokeFedCMCredential(): Promise<void> {
|
|
256
|
+
if (!this.isFedCMSupported()) {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
try {
|
|
261
|
+
// FedCM logout API (if available)
|
|
262
|
+
if ('IdentityCredential' in window && 'logout' in (window as any).IdentityCredential) {
|
|
263
|
+
const clientId = this.getClientId();
|
|
264
|
+
await (window as any).IdentityCredential.logout({
|
|
265
|
+
configURL: (this.constructor as any).DEFAULT_CONFIG_URL,
|
|
266
|
+
clientId,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
} catch (error) {
|
|
270
|
+
// Silent failure
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Get configuration for FedCM
|
|
276
|
+
*
|
|
277
|
+
* @returns FedCM configuration with browser support info
|
|
278
|
+
*/
|
|
279
|
+
getFedCMConfig(): FedCMConfig {
|
|
280
|
+
return {
|
|
281
|
+
enabled: this.isFedCMSupported(),
|
|
282
|
+
configURL: (this.constructor as any).DEFAULT_CONFIG_URL,
|
|
283
|
+
clientId: this.getClientId(),
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Generate a cryptographically secure nonce for FedCM
|
|
289
|
+
*
|
|
290
|
+
* @private
|
|
291
|
+
*/
|
|
292
|
+
public generateNonce(): string {
|
|
293
|
+
if (typeof window !== 'undefined' && window.crypto && window.crypto.randomUUID) {
|
|
294
|
+
return window.crypto.randomUUID();
|
|
295
|
+
}
|
|
296
|
+
// Fallback for older browsers
|
|
297
|
+
return `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Get the client ID for this origin
|
|
302
|
+
*
|
|
303
|
+
* @private
|
|
304
|
+
*/
|
|
305
|
+
public getClientId(): string {
|
|
306
|
+
if (typeof window === 'undefined') {
|
|
307
|
+
return 'unknown';
|
|
308
|
+
}
|
|
309
|
+
return window.location.origin;
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Export the mixin function as both named and default
|
|
315
|
+
export { OxyServicesFedCMMixin as FedCMMixin };
|