Skip to content

Commit 312c7c8

Browse files
committed
feat: expire authentication tokens
1 parent 0e56721 commit 312c7c8

File tree

2 files changed

+52
-3
lines changed

2 files changed

+52
-3
lines changed

src/securejoin.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::qr::check_qr;
2323
use crate::securejoin::bob::JoinerProgress;
2424
use crate::sync::Sync::*;
2525
use crate::token;
26+
use crate::tools::create_id;
2627
use crate::tools::time;
2728

2829
mod bob;
@@ -76,10 +77,21 @@ pub async fn get_securejoin_qr(context: &Context, group: Option<ChatId>) -> Resu
7677
let sync_token = token::lookup(context, Namespace::InviteNumber, grpid)
7778
.await?
7879
.is_none();
79-
// invitenumber will be used to allow starting the handshake,
80-
// auth will be used to verify the fingerprint
80+
// Invite number is used to request the inviter key.
8181
let invitenumber = token::lookup_or_new(context, Namespace::InviteNumber, grpid).await?;
82-
let auth = token::lookup_or_new(context, Namespace::Auth, grpid).await?;
82+
83+
// Auth token is used to verify the key-contact
84+
// if the token is not old
85+
// and add the contact to the group
86+
// if there is an associated group ID.
87+
//
88+
// We always generate a new auth token
89+
// because auth tokens "expire"
90+
// and can only be used to join groups
91+
// without verification afterwards.
92+
let auth = create_id();
93+
token::save(context, Namespace::Auth, grpid, &auth).await?;
94+
8395
let self_addr = context.get_primary_self_addr().await?;
8496
let self_name = context
8597
.get_config(Config::Displayname)

src/securejoin/securejoin_tests.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::time::Duration;
2+
13
use deltachat_contact_tools::EmailAddress;
24

35
use super::*;
@@ -11,6 +13,7 @@ use crate::stock_str::{self, messages_e2e_encrypted};
1113
use crate::test_utils::{
1214
TestContext, TestContextManager, TimeShiftFalsePositiveNote, get_chat_msg,
1315
};
16+
use crate::tools::SystemTime;
1417

1518
#[derive(PartialEq)]
1619
enum SetupContactCase {
@@ -800,3 +803,37 @@ async fn test_wrong_auth_token() -> Result<()> {
800803

801804
Ok(())
802805
}
806+
807+
/// Tests that scanning a QR code week later
808+
/// allows Bob to establish a contact with Alice,
809+
/// but does not mark Bob as verified for Alice.
810+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
811+
async fn test_expired_auth_token() -> Result<()> {
812+
let mut tcm = TestContextManager::new();
813+
let alice = &tcm.alice().await;
814+
let bob = &tcm.bob().await;
815+
816+
// Alice creates a QR code.
817+
let alice_qr = get_securejoin_qr(alice, None).await?;
818+
819+
// One week passes, QR code expires.
820+
SystemTime::shift(Duration::from_secs(7 * 24 * 3600));
821+
822+
// Bob scans the QR code.
823+
join_securejoin(bob, &alice_qr).await?;
824+
825+
// vc-request
826+
alice.recv_msg_trash(&bob.pop_sent_msg().await).await;
827+
828+
// vc-auth-requried
829+
bob.recv_msg_trash(&alice.pop_sent_msg().await).await;
830+
831+
// vc-request-with-auth
832+
alice.recv_msg_trash(&bob.pop_sent_msg().await).await;
833+
834+
// Bob should not be verified for Alice.
835+
let contact_bob = alice.add_or_lookup_contact_no_key(&bob).await;
836+
assert_eq!(contact_bob.is_verified(&alice).await.unwrap(), false);
837+
838+
Ok(())
839+
}

0 commit comments

Comments
 (0)