diff --git a/lib/actions/user-actions.js b/lib/actions/user-actions.js
--- a/lib/actions/user-actions.js
+++ b/lib/actions/user-actions.js
@@ -1,5 +1,6 @@
 // @flow
 
+import invariant from 'invariant';
 import * as React from 'react';
 
 import {
@@ -447,6 +448,18 @@
   );
 }
 
+const identityGenerateNonceActionTypes = Object.freeze({
+  started: 'IDENTITY_GENERATE_NONCE_STARTED',
+  success: 'IDENTITY_GENERATE_NONCE_SUCCESS',
+  failed: 'IDENTITY_GENERATE_NONCE_FAILED',
+});
+function useIdentityGenerateNonce(): () => Promise<string> {
+  const client = React.useContext(IdentityClientContext);
+  const identityClient = client?.identityClient;
+  invariant(identityClient, 'Identity client should be set');
+  return identityClient.generateNonce;
+}
+
 function mergeUserInfos(
   ...userInfoArrays: Array<$ReadOnlyArray<UserInfo>>
 ): UserInfo[] {
@@ -815,4 +828,6 @@
   useKeyserverAuth,
   identityRegisterActionTypes,
   useIdentityRegister,
+  identityGenerateNonceActionTypes,
+  useIdentityGenerateNonce,
 };
diff --git a/lib/types/identity-service-types.js b/lib/types/identity-service-types.js
--- a/lib/types/identity-service-types.js
+++ b/lib/types/identity-service-types.js
@@ -66,6 +66,7 @@
   +getOutboundKeysForUser: (
     userID: string,
   ) => Promise<UserDevicesOlmOutboundKeys[]>;
+  +generateNonce: () => Promise<string>;
 }
 
 export type IdentityServiceAuthLayer = {
diff --git a/lib/types/redux-types.js b/lib/types/redux-types.js
--- a/lib/types/redux-types.js
+++ b/lib/types/redux-types.js
@@ -423,6 +423,22 @@
       +payload: IdentityAuthResult,
       +loadingInfo: LoadingInfo,
     }
+  | {
+      +type: 'IDENTITY_GENERATE_NONCE_STARTED',
+      +payload?: void,
+      +loadingInfo: LoadingInfo,
+    }
+  | {
+      +type: 'IDENTITY_GENERATE_NONCE_FAILED',
+      +error: true,
+      +payload: Error,
+      +loadingInfo: LoadingInfo,
+    }
+  | {
+      +type: 'IDENTITY_GENERATE_NONCE_SUCCESS',
+      +payload?: void,
+      +loadingInfo: LoadingInfo,
+    }
   | {
       +type: 'CHANGE_KEYSERVER_USER_PASSWORD_STARTED',
       +payload?: void,
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
@@ -260,6 +260,7 @@
           identityAuthResultValidator,
         );
       },
+      generateNonce: commRustModule.generateNonce,
     }),
     [getAuthMetadata],
   );
diff --git a/web/grpc/identity-service-client-wrapper.js b/web/grpc/identity-service-client-wrapper.js
--- a/web/grpc/identity-service-client-wrapper.js
+++ b/web/grpc/identity-service-client-wrapper.js
@@ -313,6 +313,11 @@
 
     return assertWithValidator(identityAuthResult, identityAuthResultValidator);
   };
+
+  generateNonce: () => Promise<string> = async () => {
+    const result = await this.unauthClient.generateNonce(new Empty());
+    return result.getNonce();
+  };
 }
 
 export { IdentityServiceClientWrapper };