diff --git a/native/components/access-token-handler.react.js b/native/components/access-token-handler.react.js new file mode 100644 --- /dev/null +++ b/native/components/access-token-handler.react.js @@ -0,0 +1,43 @@ +// @flow + +import * as React from 'react'; + +import { setAccessTokenActionType } from 'lib/actions/user-actions.js'; +import type { UserLoginResponse } from 'lib/types/identity-service-types.js'; +import { useDispatch } from 'lib/utils/redux-utils.js'; + +import { getCommServicesAuthMetadataEmitter } from '../event-emitters/csa-auth-metadata-emitter.js'; +import { commCoreModule } from '../native-modules.js'; + +function AccessTokenHandler(): React.Node { + const dispatch = useDispatch(); + + React.useEffect(() => { + void (async () => { + const { accessToken } = + await commCoreModule.getCommServicesAuthMetadata(); + dispatch({ + type: setAccessTokenActionType, + payload: accessToken, + }); + })(); + }, [dispatch]); + + React.useEffect(() => { + const metadataEmitter = getCommServicesAuthMetadataEmitter(); + const subscription = metadataEmitter.addListener( + 'commServicesAuthMetadata', + (authMetadata: UserLoginResponse) => { + dispatch({ + type: setAccessTokenActionType, + payload: authMetadata.accessToken, + }); + }, + ); + return () => subscription.remove(); + }, [dispatch]); + + return null; +} + +export default AccessTokenHandler; diff --git a/native/identity-service/identity-service-context-provider.react.js b/native/identity-service/identity-service-context-provider.react.js --- a/native/identity-service/identity-service-context-provider.react.js +++ b/native/identity-service/identity-service-context-provider.react.js @@ -12,14 +12,15 @@ type DeviceOlmOutboundKeys, deviceOlmOutboundKeysValidator, type IdentityServiceClient, - ONE_TIME_KEYS_NUMBER, type UserDevicesOlmOutboundKeys, type UserLoginResponse, } from 'lib/types/identity-service-types.js'; +import { ONE_TIME_KEYS_NUMBER } from 'lib/types/identity-service-types.js'; import { assertWithValidator } from 'lib/utils/validation-utils.js'; import { getCommServicesAuthMetadataEmitter } from '../event-emitters/csa-auth-metadata-emitter.js'; import { commCoreModule, commRustModule } from '../native-modules.js'; +import { useSelector } from '../redux/redux-utils.js'; import { getContentSigningKey } from '../utils/crypto-utils.js'; type Props = { @@ -28,13 +29,11 @@ function IdentityServiceContextProvider(props: Props): React.Node { const { children } = props; - const authMetadataPromiseRef = - React.useRef>(); - if (!authMetadataPromiseRef.current) { - authMetadataPromiseRef.current = (async () => { - const { userID, accessToken } = - await commCoreModule.getCommServicesAuthMetadata(); - return { userID, accessToken }; + const userIDPromiseRef = React.useRef>(); + if (!userIDPromiseRef.current) { + userIDPromiseRef.current = (async () => { + const { userID } = await commCoreModule.getCommServicesAuthMetadata(); + return userID; })(); } @@ -43,15 +42,14 @@ const subscription = metadataEmitter.addListener( 'commServicesAuthMetadata', (authMetadata: UserLoginResponse) => { - authMetadataPromiseRef.current = Promise.resolve({ - userID: authMetadata.userId, - accessToken: authMetadata.accessToken, - }); + userIDPromiseRef.current = Promise.resolve(authMetadata.userId); }, ); return () => subscription.remove(); }, []); + const accessToken = useSelector(state => state.commServicesAccessToken); + const getAuthMetadata = React.useCallback< () => Promise<{ +deviceID: string, @@ -60,29 +58,35 @@ }>, >(async () => { const deviceID = await getContentSigningKey(); - const authMetadata = await authMetadataPromiseRef.current; - const userID = authMetadata?.userID; - const accessToken = authMetadata?.accessToken; + const userID = await userIDPromiseRef.current; if (!deviceID || !userID || !accessToken) { throw new Error('Identity service client is not initialized'); } return { deviceID, userID, accessToken }; - }, []); + }, [accessToken]); const client = React.useMemo( () => ({ deleteUser: async () => { - const { deviceID, userID, accessToken } = await getAuthMetadata(); - return commRustModule.deleteUser(userID, deviceID, accessToken); + const { + deviceID, + userID, + accessToken: token, + } = await getAuthMetadata(); + return commRustModule.deleteUser(userID, deviceID, token); }, getKeyserverKeys: async ( keyserverID: string, ): Promise => { - const { deviceID, userID, accessToken } = await getAuthMetadata(); + const { + deviceID, + userID, + accessToken: token, + } = await getAuthMetadata(); const result = await commRustModule.getKeyserverKeys( userID, deviceID, - accessToken, + token, keyserverID, ); const resultObject = JSON.parse(result); @@ -122,12 +126,12 @@ const { deviceID: authDeviceID, userID, - accessToken, + accessToken: token, } = await getAuthMetadata(); const result = await commRustModule.getOutboundKeysForUser( userID, authDeviceID, - accessToken, + token, targetUserID, ); const resultArray = JSON.parse(result); @@ -218,8 +222,8 @@ getOneTimeKeyArray(primaryOneTimeKeys), getOneTimeKeyArray(notificationsOneTimeKeys), ); - const { userID, accessToken } = JSON.parse(registrationResult); - return { accessToken, userID, username }; + const { userID, accessToken: token } = JSON.parse(registrationResult); + return { accessToken: token, userID, username }; }, }), [getAuthMetadata], diff --git a/native/root.react.js b/native/root.react.js --- a/native/root.react.js +++ b/native/root.react.js @@ -40,6 +40,7 @@ import { BottomSheetProvider } from './bottom-sheet/bottom-sheet-provider.react.js'; import ChatContextProvider from './chat/chat-context-provider.react.js'; import MessageEditingContextProvider from './chat/message-editing-context-provider.react.js'; +import AccessTokenHandler from './components/access-token-handler.react.js'; import { FeatureFlagsProvider } from './components/feature-flags-provider.react.js'; import PersistedStateGate from './components/persisted-state-gate.js'; import PrekeysHandler from './components/prekeys-handler.react.js'; @@ -273,6 +274,7 @@ + ); let navigation;