Page MenuHomePhabricator

D10455.id36122.diff
No OneTemporary

D10455.id36122.diff

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
@@ -54,6 +54,10 @@
username: string,
password: string,
) => Promise<IdentityAuthResult>;
+ +logInPasswordUser: (
+ username: string,
+ password: string,
+ ) => Promise<IdentityAuthResult>;
}
export type IdentityServiceAuthLayer = {
@@ -94,3 +98,12 @@
};
export const ONE_TIME_KEYS_NUMBER = 10;
+
+export const identityDeviceTypes = Object.freeze({
+ KEYSERVER: 0,
+ WEB: 1,
+ IOS: 2,
+ ANDROID: 3,
+ WINDOWS: 4,
+ MAC_OS: 5,
+});
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
@@ -134,6 +134,34 @@
const { userID, accessToken } = JSON.parse(registrationResult);
return { accessToken, userID, username };
},
+ logInPasswordUser: async (username: string, password: string) => {
+ await commCoreModule.initializeCryptoAccount();
+ const [
+ { blobPayload, signature },
+ notificationsOneTimeKeys,
+ primaryOneTimeKeys,
+ prekeys,
+ ] = await Promise.all([
+ commCoreModule.getUserPublicKey(),
+ commCoreModule.getNotificationsOneTimeKeys(ONE_TIME_KEYS_NUMBER),
+ commCoreModule.getPrimaryOneTimeKeys(ONE_TIME_KEYS_NUMBER),
+ commCoreModule.generateAndGetPrekeys(),
+ ]);
+ const loginResult = await commRustModule.logInPasswordUser(
+ username,
+ password,
+ blobPayload,
+ signature,
+ prekeys.contentPrekey,
+ prekeys.contentPrekeySignature,
+ prekeys.notifPrekey,
+ prekeys.notifPrekeySignature,
+ getOneTimeKeyArray(primaryOneTimeKeys),
+ getOneTimeKeyArray(notificationsOneTimeKeys),
+ );
+ const { userID, accessToken } = JSON.parse(loginResult);
+ return { accessToken, userID, username };
+ },
}),
[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
@@ -1,30 +1,49 @@
// @flow
+import { Login } from '@commapp/opaque-ke-wasm';
+
import identityServiceConfig from 'lib/facts/identity-service.js';
import {
type IdentityServiceAuthLayer,
type IdentityServiceClient,
type KeyserverKeys,
+ type IdentityAuthResult,
+ type IdentityDeviceKeyUpload,
keyserverKeysValidator,
+ identityDeviceTypes,
} from 'lib/types/identity-service-types.js';
+import { getMessageForException } from 'lib/utils/errors.js';
import { assertWithValidator } from 'lib/utils/validation-utils.js';
import { VersionInterceptor, AuthInterceptor } from './interceptor.js';
+import { initOpaque } from '../crypto/opaque-utils.js';
import * as IdentityAuthClient from '../protobufs/identity-auth-client.cjs';
import * as IdentityAuthStructs from '../protobufs/identity-auth-structs.cjs';
-import { Empty } from '../protobufs/identity-unauth-structs.cjs';
+import {
+ DeviceKeyUpload,
+ Empty,
+ IdentityKeyInfo,
+ OpaqueLoginFinishRequest,
+ OpaqueLoginStartRequest,
+ Prekey,
+} from '../protobufs/identity-unauth-structs.cjs';
import * as IdentityUnauthClient from '../protobufs/identity-unauth.cjs';
class IdentityServiceClientWrapper implements IdentityServiceClient {
authClient: ?IdentityAuthClient.IdentityClientServicePromiseClient;
unauthClient: IdentityUnauthClient.IdentityClientServicePromiseClient;
+ getDeviceKeyUpload: () => Promise<IdentityDeviceKeyUpload>;
- constructor(authLayer: ?IdentityServiceAuthLayer) {
+ constructor(
+ authLayer: ?IdentityServiceAuthLayer,
+ getDeviceKeyUpload: () => Promise<IdentityDeviceKeyUpload>,
+ ) {
if (authLayer) {
this.authClient =
IdentityServiceClientWrapper.createAuthClient(authLayer);
}
this.unauthClient = IdentityServiceClientWrapper.createUnauthClient();
+ this.getDeviceKeyUpload = getDeviceKeyUpload;
}
static determineSocketAddr(): string {
@@ -124,6 +143,104 @@
return assertWithValidator(keyserverKeys, keyserverKeysValidator);
};
+
+ logInPasswordUser: (
+ username: string,
+ password: string,
+ ) => Promise<IdentityAuthResult> = async (
+ username: string,
+ password: string,
+ ) => {
+ const client = this.unauthClient;
+ if (!client) {
+ throw new Error('Identity service client is not initialized');
+ }
+
+ const [identityDeviceKeyUpload] = await Promise.all([
+ this.getDeviceKeyUpload(),
+ initOpaque(),
+ ]);
+
+ const {
+ keyPayload,
+ keyPayloadSignature,
+ contentPrekey,
+ contentPrekeySignature,
+ notifPrekey,
+ notifPrekeySignature,
+ contentOneTimeKeys,
+ notifOneTimeKeys,
+ } = identityDeviceKeyUpload;
+
+ const contentOneTimeKeysArray = Array.from(contentOneTimeKeys);
+ const notifOneTimeKeysArray = Array.from(notifOneTimeKeys);
+
+ const opaqueLogin = new Login();
+ const startRequestBytes = opaqueLogin.start(password);
+
+ const identityKeyInfo = new IdentityKeyInfo();
+ identityKeyInfo.setPayload(keyPayload);
+ identityKeyInfo.setPayloadSignature(keyPayloadSignature);
+
+ const contentPrekeyUpload = new Prekey();
+ contentPrekeyUpload.setPrekey(contentPrekey);
+ contentPrekeyUpload.setPrekeySignature(contentPrekeySignature);
+
+ const notifPrekeyUpload = new Prekey();
+ notifPrekeyUpload.setPrekey(notifPrekey);
+ notifPrekeyUpload.setPrekeySignature(notifPrekeySignature);
+
+ const deviceKeyUpload = new DeviceKeyUpload();
+ deviceKeyUpload.setDeviceKeyInfo(identityKeyInfo);
+ deviceKeyUpload.setContentUpload(contentPrekeyUpload);
+ deviceKeyUpload.setNotifUpload(notifPrekeyUpload);
+ deviceKeyUpload.setOneTimeContentPrekeysList(contentOneTimeKeysArray);
+ deviceKeyUpload.setOneTimeNotifPrekeysList(notifOneTimeKeysArray);
+ deviceKeyUpload.setDeviceType(identityDeviceTypes.WEB);
+
+ const loginStartRequest = new OpaqueLoginStartRequest();
+ loginStartRequest.setUsername(username);
+ loginStartRequest.setOpaqueLoginRequest(startRequestBytes);
+ loginStartRequest.setDeviceKeyUpload(deviceKeyUpload);
+
+ let loginStartResponse;
+ try {
+ loginStartResponse =
+ await client.logInPasswordUserStart(loginStartRequest);
+ } catch (e) {
+ console.log('Error calling logInPasswordUserStart:', e);
+ throw new Error(
+ `logInPasswordUserStart RPC failed: ${
+ getMessageForException(e) ?? 'unknown'
+ }`,
+ );
+ }
+ const finishRequestBytes = opaqueLogin.finish(
+ loginStartResponse.getOpaqueLoginResponse_asU8(),
+ );
+
+ const loginFinishRequest = new OpaqueLoginFinishRequest();
+ loginFinishRequest.setSessionId(loginStartResponse.getSessionId());
+ loginFinishRequest.setOpaqueLoginUpload(finishRequestBytes);
+
+ let loginFinishResponse;
+ try {
+ loginFinishResponse =
+ await client.logInPasswordUserFinish(loginFinishRequest);
+ } catch (e) {
+ console.log('Error calling logInPasswordUserFinish:', e);
+ throw new Error(
+ `logInPasswordUserFinish RPC failed: ${
+ getMessageForException(e) ?? 'unknown'
+ }`,
+ );
+ }
+
+ const userID = loginFinishResponse.getUserId();
+ const accessToken = loginFinishResponse.getAccessToken();
+
+ return { userID, accessToken, username };
+ };
}
export { IdentityServiceClientWrapper };
diff --git a/web/grpc/identity-service-context-provider.react.js b/web/grpc/identity-service-context-provider.react.js
--- a/web/grpc/identity-service-context-provider.react.js
+++ b/web/grpc/identity-service-context-provider.react.js
@@ -5,6 +5,7 @@
import { IdentityClientContext } from 'lib/shared/identity-client-context.js';
import { IdentityServiceClientWrapper } from './identity-service-client-wrapper.js';
+import { useGetDeviceKeyUpload } from '../account/account-hooks.js';
import { useSelector } from '../redux/redux-utils.js';
type Props = {
@@ -18,6 +19,7 @@
const deviceID = useSelector(
state => state.cryptoStore?.primaryIdentityKeys.ed25519,
);
+ const getDeviceKeyUpload = useGetDeviceKeyUpload();
const client = React.useMemo(() => {
let authLayer = null;
@@ -28,8 +30,8 @@
commServicesAccessToken: accessToken,
};
}
- return new IdentityServiceClientWrapper(authLayer);
- }, [accessToken, deviceID, userID]);
+ return new IdentityServiceClientWrapper(authLayer, getDeviceKeyUpload);
+ }, [accessToken, deviceID, getDeviceKeyUpload, userID]);
const value = React.useMemo(
() => ({

File Metadata

Mime Type
text/plain
Expires
Thu, Dec 5, 10:56 AM (16 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2616830
Default Alt Text
D10455.id36122.diff (8 KB)

Event Timeline