Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3564039
D7539.id25637.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Referenced Files
None
Subscribers
None
D7539.id25637.diff
View Options
diff --git a/services/identity/src/client_service.rs b/services/identity/src/client_service.rs
--- a/services/identity/src/client_service.rs
+++ b/services/identity/src/client_service.rs
@@ -49,6 +49,7 @@
#[derive(Clone)]
pub struct UserLoginInfo {
+ pub user_id: String,
pub flattened_device_key_upload: FlattenedDeviceKeyUpload,
pub opaque_server_login: comm_opaque2::server::Login,
}
@@ -229,9 +230,9 @@
) -> Result<tonic::Response<OpaqueLoginStartResponse>, tonic::Status> {
let message = request.into_inner();
- let password_file_bytes = self
+ let (user_id, password_file_bytes) = self
.client
- .get_password_file_from_username(&message.username)
+ .get_user_id_and_password_file_from_username(&message.username)
.await
.map_err(handle_db_error)?
.ok_or(tonic::Status::not_found("user not found"))?;
@@ -275,6 +276,7 @@
let key_info = KeyPayload::from_str(&payload)
.map_err(|_| tonic::Status::invalid_argument("malformed payload"))?;
let login_state = UserLoginInfo {
+ user_id,
opaque_server_login: server_login,
flattened_device_key_upload: FlattenedDeviceKeyUpload {
device_id_key: key_info.primary_identity_public_keys.curve25519,
@@ -306,9 +308,50 @@
async fn login_password_user_finish(
&self,
- _request: tonic::Request<OpaqueLoginFinishRequest>,
+ request: tonic::Request<OpaqueLoginFinishRequest>,
) -> Result<tonic::Response<OpaqueLoginFinishResponse>, tonic::Status> {
- unimplemented!();
+ let message = request.into_inner();
+
+ if let Some(WorkflowInProgress::Login(state)) =
+ self.cache.get(&message.session_id)
+ {
+ self.cache.invalidate(&message.session_id).await;
+
+ let mut server_login = state.opaque_server_login.clone();
+ server_login
+ .finish(&message.opaque_login_upload)
+ .map_err(protocol_error_to_grpc_status)?;
+
+ self
+ .client
+ .add_device_to_users_table(state.clone())
+ .await
+ .map_err(handle_db_error)?;
+
+ // Create access token
+ let token = AccessTokenData::new(
+ message.session_id,
+ state.flattened_device_key_upload.device_id_key,
+ crate::token::AuthType::Password,
+ &mut OsRng,
+ );
+
+ let access_token = token.access_token.clone();
+
+ self
+ .client
+ .put_access_token_data(token)
+ .await
+ .map_err(handle_db_error)?;
+
+ let response = OpaqueLoginFinishResponse {
+ user_id: state.user_id,
+ access_token,
+ };
+ Ok(Response::new(response))
+ } else {
+ Err(tonic::Status::not_found("session not found"))
+ }
}
async fn login_wallet_user(
diff --git a/services/identity/src/database.rs b/services/identity/src/database.rs
--- a/services/identity/src/database.rs
+++ b/services/identity/src/database.rs
@@ -11,11 +11,11 @@
use aws_sdk_dynamodb::types::Blob;
use aws_sdk_dynamodb::{Client, Error as DynamoDBError};
use chrono::{DateTime, Utc};
-use opaque_ke::{errors::ProtocolError, ServerRegistration};
+use opaque_ke::errors::ProtocolError;
use serde::{Deserialize, Serialize};
use tracing::{debug, error, info, warn};
-use crate::client_service::UserRegistrationInfo;
+use crate::client_service::{UserLoginInfo, UserRegistrationInfo};
use crate::config::CONFIG;
use crate::constants::{
ACCESS_TOKEN_SORT_KEY, ACCESS_TOKEN_TABLE,
@@ -40,7 +40,6 @@
use crate::id::generate_uuid;
use crate::nonce::NonceData;
use crate::token::{AccessTokenData, AuthType};
-use comm_opaque::Cipher;
#[derive(Serialize, Deserialize)]
pub struct OlmKeys {
@@ -222,6 +221,109 @@
Ok(user_id)
}
+
+ pub async fn add_device_to_users_table(
+ &self,
+ login_state: UserLoginInfo,
+ ) -> Result<(), Error> {
+ let device_info = HashMap::from([
+ (
+ USERS_TABLE_DEVICES_MAP_DEVICE_TYPE_ATTRIBUTE_NAME.to_string(),
+ AttributeValue::S(Device::Client.to_string()),
+ ),
+ (
+ USERS_TABLE_DEVICES_MAP_KEY_PAYLOAD_ATTRIBUTE_NAME.to_string(),
+ AttributeValue::S(login_state.flattened_device_key_upload.key_payload),
+ ),
+ (
+ USERS_TABLE_DEVICES_MAP_KEY_PAYLOAD_SIGNATURE_ATTRIBUTE_NAME
+ .to_string(),
+ AttributeValue::S(
+ login_state
+ .flattened_device_key_upload
+ .key_payload_signature,
+ ),
+ ),
+ (
+ USERS_TABLE_DEVICES_MAP_IDENTITY_PREKEY_ATTRIBUTE_NAME.to_string(),
+ AttributeValue::S(
+ login_state.flattened_device_key_upload.identity_prekey,
+ ),
+ ),
+ (
+ USERS_TABLE_DEVICES_MAP_IDENTITY_PREKEY_SIGNATURE_ATTRIBUTE_NAME
+ .to_string(),
+ AttributeValue::S(
+ login_state
+ .flattened_device_key_upload
+ .identity_prekey_signature,
+ ),
+ ),
+ (
+ USERS_TABLE_DEVICES_MAP_IDENTITY_ONETIME_KEYS_ATTRIBUTE_NAME
+ .to_string(),
+ AttributeValue::L(
+ login_state
+ .flattened_device_key_upload
+ .identity_onetime_keys
+ .into_iter()
+ .map(AttributeValue::S)
+ .collect(),
+ ),
+ ),
+ (
+ USERS_TABLE_DEVICES_MAP_NOTIF_PREKEY_ATTRIBUTE_NAME.to_string(),
+ AttributeValue::S(login_state.flattened_device_key_upload.notif_prekey),
+ ),
+ (
+ USERS_TABLE_DEVICES_MAP_NOTIF_PREKEY_SIGNATURE_ATTRIBUTE_NAME
+ .to_string(),
+ AttributeValue::S(
+ login_state
+ .flattened_device_key_upload
+ .notif_prekey_signature,
+ ),
+ ),
+ (
+ USERS_TABLE_DEVICES_MAP_NOTIF_ONETIME_KEYS_ATTRIBUTE_NAME.to_string(),
+ AttributeValue::L(
+ login_state
+ .flattened_device_key_upload
+ .notif_onetime_keys
+ .into_iter()
+ .map(AttributeValue::S)
+ .collect(),
+ ),
+ ),
+ ]);
+
+ let update_expression =
+ format!("SET {}.#{} = :v", USERS_TABLE_DEVICES_ATTRIBUTE, "deviceID",);
+ let expression_attribute_names = HashMap::from([(
+ format!("#{}", "deviceID"),
+ login_state.flattened_device_key_upload.device_id_key,
+ )]);
+ let expression_attribute_values =
+ HashMap::from([(":v".to_string(), AttributeValue::M(device_info))]);
+
+ self
+ .client
+ .update_item()
+ .table_name(USERS_TABLE)
+ .key(
+ USERS_TABLE_PARTITION_KEY,
+ AttributeValue::S(login_state.user_id),
+ )
+ .update_expression(update_expression)
+ .set_expression_attribute_names(Some(expression_attribute_names))
+ .set_expression_attribute_values(Some(expression_attribute_values))
+ .send()
+ .await
+ .map_err(|e| Error::AwsSdk(e.into()))?;
+
+ Ok(())
+ }
+
pub async fn delete_user(
&self,
user_id: String,
@@ -444,19 +546,25 @@
}
}
- pub async fn get_password_file_from_username(
+ pub async fn get_user_id_and_password_file_from_username(
&self,
username: &str,
- ) -> Result<Option<Vec<u8>>, Error> {
+ ) -> Result<Option<(String, Vec<u8>)>, Error> {
match self
.get_user_from_user_info(username.to_string(), AuthType::Password)
.await
{
- Ok(Some(mut user)) => parse_registration_data_attribute(
- user.remove(USERS_TABLE_REGISTRATION_ATTRIBUTE),
- )
- .map(Some)
- .map_err(Error::Attribute),
+ Ok(Some(mut user)) => {
+ let user_id = parse_string_attribute(
+ USERS_TABLE_PARTITION_KEY,
+ user.remove(USERS_TABLE_PARTITION_KEY),
+ )?;
+ let password_file = parse_registration_data_attribute(
+ user.remove(USERS_TABLE_REGISTRATION_ATTRIBUTE),
+ )?;
+
+ Ok(Some((user_id, password_file)))
+ }
Ok(_) => {
info!(
"No item found for user {} in PAKE registration table",
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 28, 1:01 PM (6 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2720195
Default Alt Text
D7539.id25637.diff (7 KB)
Attached To
Mode
D7539: [identity] finish login
Attached
Detach File
Event Timeline
Log In to Comment