Page MenuHomePhabricator

D6914.id23269.diff
No OneTemporary

D6914.id23269.diff

diff --git a/keyserver/addons/rust-node-addon/src/identity_client/login_user.rs b/keyserver/addons/rust-node-addon/src/identity_client/login_user.rs
new file mode 100644
--- /dev/null
+++ b/keyserver/addons/rust-node-addon/src/identity_client/login_user.rs
@@ -0,0 +1,136 @@
+use super::*;
+
+#[napi]
+#[instrument(skip_all)]
+async fn login_user_pake(
+ user_id: String,
+ signing_public_key: String,
+ password: String,
+ session_initialization_info: HashMap<String, String>,
+) -> Result<String> {
+ let channel = Channel::from_static(&IDENTITY_SERVICE_SOCKET_ADDR)
+ .connect()
+ .await
+ .map_err(|_| {
+ Error::new(
+ Status::GenericFailure,
+ "Unable to connect to identity service".to_string(),
+ )
+ })?;
+ let token: MetadataValue<_> = AUTH_TOKEN
+ .parse()
+ .map_err(|_| Error::from_status(Status::GenericFailure))?;
+ let mut identity_client =
+ IdentityServiceClient::with_interceptor(channel, |mut req: Request<()>| {
+ req.metadata_mut().insert("authorization", token.clone());
+ Ok(req)
+ });
+
+ // Create a LoginRequest channel and use ReceiverStream to turn the
+ // MPSC receiver into a Stream for outbound messages
+ let (tx, rx) = mpsc::channel(1);
+ let stream = ReceiverStream::new(rx);
+ let request = Request::new(stream);
+
+ // `response` is the Stream for inbound messages
+ let mut response = identity_client
+ .login_user(request)
+ .await
+ .map_err(|_| Error::from_status(Status::GenericFailure))?
+ .into_inner();
+
+ // Start PAKE login on client and send initial login request to Identity
+ // service
+ let mut client_rng = OsRng;
+ let client_login_start_result = pake_login_start(&mut client_rng, &password)?;
+ let login_request = LoginRequest {
+ data: Some(PakeLoginRequest(PakeLoginRequestStruct {
+ data: Some(PakeCredentialRequestAndUserId(
+ PakeCredentialRequestAndUserIdStruct {
+ user_id,
+ signing_public_key,
+ pake_credential_request: client_login_start_result
+ .message
+ .serialize()
+ .map_err(|e| {
+ error!("Could not serialize credential request: {}", e);
+ Error::new(Status::GenericFailure, e.to_string())
+ })?,
+ session_initialization_info: Some(SessionInitializationInfo {
+ info: session_initialization_info,
+ }),
+ },
+ )),
+ })),
+ };
+
+ send_to_mpsc(tx.clone(), login_request).await?;
+
+ // Handle responses from Identity service sequentially, making sure we get
+ // messages in the correct order
+
+ // Finish PAKE login; send final login request to Identity service
+ let message = response.message().await.map_err(|e| {
+ error!("Received an error from inbound message stream: {}", e);
+ Error::from_status(Status::GenericFailure)
+ })?;
+ handle_login_credential_response(
+ message,
+ client_login_start_result.state,
+ tx,
+ )
+ .await?;
+
+ // Return access token
+ let message = response.message().await.map_err(|e| {
+ error!("Received an error from inbound message stream: {}", e);
+ Error::from_status(Status::GenericFailure)
+ })?;
+ handle_login_token_response(message)
+}
+
+async fn handle_login_credential_response(
+ message: Option<LoginResponse>,
+ client_login: ClientLogin<Cipher>,
+ tx: mpsc::Sender<LoginRequest>,
+) -> Result<(), Status> {
+ if let Some(LoginResponse {
+ data:
+ Some(LoginPakeLoginResponse(PakeLoginResponseStruct {
+ data: Some(PakeCredentialResponse(credential_response_bytes)),
+ })),
+ }) = message
+ {
+ let login_request = LoginRequest {
+ data: Some(PakeLoginRequest(PakeLoginRequestStruct {
+ data: Some(LoginPakeCredentialFinalization(
+ pake_login_finish(&credential_response_bytes, client_login)?
+ .serialize()
+ .map_err(|e| {
+ error!("Could not serialize credential request: {}", e);
+ Error::from_status(Status::GenericFailure)
+ })?,
+ )),
+ })),
+ };
+ send_to_mpsc(tx, login_request).await
+ } else {
+ Err(handle_unexpected_response(message))
+ }
+}
+
+fn handle_login_token_response(
+ message: Option<LoginResponse>,
+) -> Result<String, Status> {
+ if let Some(LoginResponse {
+ data:
+ Some(LoginPakeLoginResponse(PakeLoginResponseStruct {
+ data: Some(AccessToken(access_token)),
+ })),
+ }) = message
+ {
+ Ok(access_token)
+ } else {
+ Err(handle_unexpected_response(message))
+ }
+}
diff --git a/keyserver/addons/rust-node-addon/src/identity_client/mod.rs b/keyserver/addons/rust-node-addon/src/identity_client/mod.rs
--- a/keyserver/addons/rust-node-addon/src/identity_client/mod.rs
+++ b/keyserver/addons/rust-node-addon/src/identity_client/mod.rs
@@ -1,4 +1,5 @@
pub mod delete_user;
+pub mod login_user;
pub mod register_user;
pub mod identity {
tonic::include_proto!("identity");
@@ -7,6 +8,10 @@
use comm_opaque::Cipher;
use identity::identity_service_client::IdentityServiceClient;
use identity::{
+ login_request::Data::PakeLoginRequest,
+ login_response::Data::PakeLoginResponse as LoginPakeLoginResponse,
+ pake_login_request::Data::PakeCredentialFinalization as LoginPakeCredentialFinalization,
+ pake_login_request::Data::PakeCredentialRequestAndUserId,
pake_login_response::Data::AccessToken,
pake_login_response::Data::PakeCredentialResponse,
registration_request::Data::PakeCredentialFinalization as RegistrationPakeCredentialFinalization,
@@ -14,6 +19,9 @@
registration_request::Data::PakeRegistrationUploadAndCredentialRequest,
registration_response::Data::PakeLoginResponse as RegistrationPakeLoginResponse,
registration_response::Data::PakeRegistrationResponse, DeleteUserRequest,
+ LoginRequest, LoginResponse,
+ PakeCredentialRequestAndUserId as PakeCredentialRequestAndUserIdStruct,
+ PakeLoginRequest as PakeLoginRequestStruct,
PakeLoginResponse as PakeLoginResponseStruct,
PakeRegistrationRequestAndUserId as PakeRegistrationRequestAndUserIdStruct,
PakeRegistrationUploadAndCredentialRequest as PakeRegistrationUploadAndCredentialRequestStruct,
diff --git a/keyserver/src/responders/user-responders.js b/keyserver/src/responders/user-responders.js
--- a/keyserver/src/responders/user-responders.js
+++ b/keyserver/src/responders/user-responders.js
@@ -1,6 +1,7 @@
// @flow
import invariant from 'invariant';
+import { getRustAPI } from 'rust-node-addon';
import { ErrorTypes, SiweMessage } from 'siwe';
import t from 'tcomb';
import bcrypt from 'twin-bcrypt';
@@ -64,6 +65,7 @@
normalizeCalendarQuery,
verifyCalendarQueryThreadIDs,
} from './entry-responders.js';
+import { handleAsyncPromise } from './handlers.js';
import {
createAccount,
processSIWEAccountCreation,
@@ -344,11 +346,10 @@
await validateInput(viewer, logInRequestInputValidator, input);
const request: LogInRequest = input;
+ let identityKeys: ?IdentityKeysBlob;
const { signedIdentityKeysBlob } = request;
if (signedIdentityKeysBlob) {
- const identityKeys: IdentityKeysBlob = JSON.parse(
- signedIdentityKeysBlob.payload,
- );
+ identityKeys = JSON.parse(signedIdentityKeysBlob.payload);
const olmUtil: OLMUtility = getOLMUtility();
try {
@@ -384,8 +385,10 @@
WHERE LCASE(username) = LCASE(${username})
`;
promises.userQuery = dbQuery(userQuery);
+ promises.rustAPI = getRustAPI();
const {
userQuery: [userResult],
+ rustAPI,
} = await promiseAll(promises);
if (userResult.length === 0) {
@@ -403,6 +406,21 @@
}
const id = userRow.id.toString();
+
+ if (identityKeys && signedIdentityKeysBlob) {
+ handleAsyncPromise(
+ rustAPI.loginUserPake(
+ id,
+ identityKeys.primaryIdentityPublicKeys.ed25519,
+ request.password,
+ {
+ payload: signedIdentityKeysBlob.payload,
+ signature: signedIdentityKeysBlob.signature,
+ },
+ ),
+ );
+ }
+
return await processSuccessfulLogin({
viewer,
input,
diff --git a/lib/types/rust-binding-types.js b/lib/types/rust-binding-types.js
--- a/lib/types/rust-binding-types.js
+++ b/lib/types/rust-binding-types.js
@@ -21,6 +21,12 @@
password: string,
userPublicKey: string,
) => Promise<string>,
+ +loginUserPake: (
+ userId: string,
+ signingPublicKey: string,
+ password: string,
+ sessionInitializationInfo: Object,
+ ) => Promise<string>,
+deleteUser: (userId: string) => Promise<boolean>,
+TunnelbrokerClient: Class<TunnelbrokerClientClass>,
};

File Metadata

Mime Type
text/plain
Expires
Mon, Dec 23, 6:05 PM (18 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2695671
Default Alt Text
D6914.id23269.diff (8 KB)

Event Timeline