diff --git a/services/identity/src/constants.rs b/services/identity/src/constants.rs --- a/services/identity/src/constants.rs +++ b/services/identity/src/constants.rs @@ -80,6 +80,9 @@ pub const NONCE_TABLE: &str = "identity-nonces"; pub const NONCE_TABLE_PARTITION_KEY: &str = "nonce"; pub const NONCE_TABLE_CREATED_ATTRIBUTE: &str = "created"; +pub const NONCE_TABLE_EXPIRATION_TIME_ATTRIBUTE: &str = "expirationTime"; +pub const NONCE_TABLE_EXPIRATION_TIME_UNIX_ATTRIBUTE: &str = + "expirationTimeUnix"; // Usernames reserved because they exist in Ashoat's keyserver already pub const RESERVED_USERNAMES_TABLE: &str = "identity-reserved-usernames"; @@ -102,6 +105,7 @@ // Nonce pub const NONCE_LENGTH: usize = 17; +pub const NONCE_TTL_DURATION: i64 = 30; // LocalStack 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 @@ -22,7 +22,8 @@ ACCESS_TOKEN_TABLE_AUTH_TYPE_ATTRIBUTE, ACCESS_TOKEN_TABLE_CREATED_ATTRIBUTE, ACCESS_TOKEN_TABLE_PARTITION_KEY, ACCESS_TOKEN_TABLE_TOKEN_ATTRIBUTE, ACCESS_TOKEN_TABLE_VALID_ATTRIBUTE, NONCE_TABLE, - NONCE_TABLE_CREATED_ATTRIBUTE, NONCE_TABLE_PARTITION_KEY, + NONCE_TABLE_CREATED_ATTRIBUTE, NONCE_TABLE_EXPIRATION_TIME_ATTRIBUTE, + NONCE_TABLE_EXPIRATION_TIME_UNIX_ATTRIBUTE, NONCE_TABLE_PARTITION_KEY, RESERVED_USERNAMES_TABLE, RESERVED_USERNAMES_TABLE_PARTITION_KEY, USERS_TABLE, USERS_TABLE_DEVICES_ATTRIBUTE, USERS_TABLE_DEVICES_MAP_CONTENT_ONETIME_KEYS_ATTRIBUTE_NAME, @@ -479,7 +480,7 @@ item: Some(mut item), .. }) => { - let created = parse_created_attribute( + let created = parse_date_time_attribute( ACCESS_TOKEN_TABLE_CREATED_ATTRIBUTE, item.remove(ACCESS_TOKEN_TABLE_CREATED_ATTRIBUTE), )?; @@ -813,6 +814,14 @@ NONCE_TABLE_CREATED_ATTRIBUTE.to_string(), AttributeValue::S(nonce_data.created.to_rfc3339()), ), + ( + NONCE_TABLE_EXPIRATION_TIME_ATTRIBUTE.to_string(), + AttributeValue::S(nonce_data.expiration_time.to_rfc3339()), + ), + ( + NONCE_TABLE_EXPIRATION_TIME_UNIX_ATTRIBUTE.to_string(), + AttributeValue::N(nonce_data.expiration_time.timestamp().to_string()), + ), ]); self .client @@ -849,12 +858,21 @@ item.remove(&NONCE_TABLE_PARTITION_KEY.to_string()), )?; - let created = parse_created_attribute( + let created = parse_date_time_attribute( NONCE_TABLE_CREATED_ATTRIBUTE, item.remove(&NONCE_TABLE_CREATED_ATTRIBUTE.to_string()), )?; - Ok(Some(NonceData { nonce, created })) + let expiration_time = parse_date_time_attribute( + NONCE_TABLE_EXPIRATION_TIME_ATTRIBUTE, + item.remove(&NONCE_TABLE_EXPIRATION_TIME_ATTRIBUTE.to_string()), + )?; + + Ok(Some(NonceData { + nonce, + created, + expiration_time, + })) } pub async fn remove_nonce_from_nonces_table( @@ -981,7 +999,7 @@ primary_key } -fn parse_created_attribute( +fn parse_date_time_attribute( attribute_name: &str, attribute: Option, ) -> Result, DBItemError> { diff --git a/services/identity/src/nonce.rs b/services/identity/src/nonce.rs --- a/services/identity/src/nonce.rs +++ b/services/identity/src/nonce.rs @@ -1,15 +1,20 @@ -use chrono::{DateTime, Utc}; +use chrono::{DateTime, Duration, Utc}; use rand::{ distributions::{Alphanumeric, DistString}, CryptoRng, Rng, }; use crate::constants::NONCE_LENGTH; +use crate::constants::NONCE_TTL_DURATION; pub fn generate_nonce_data(rng: &mut (impl Rng + CryptoRng)) -> NonceData { + let nonce = Alphanumeric.sample_string(rng, NONCE_LENGTH); + let created = Utc::now(); + let expiration_time = created + Duration::minutes(NONCE_TTL_DURATION); NonceData { - nonce: Alphanumeric.sample_string(rng, NONCE_LENGTH), - created: Utc::now(), + nonce, + created, + expiration_time, } } @@ -17,4 +22,5 @@ pub struct NonceData { pub nonce: String, pub created: DateTime, + pub expiration_time: DateTime, }