Skip to content

Commit 4a17eb9

Browse files
committed
feat(qr-code): Add yet another state to the login granting process
This separates the step of opening the verification URI in a browser and closing the browser.
1 parent b4651ab commit 4a17eb9

2 files changed

Lines changed: 109 additions & 30 deletions

File tree

  • bindings/matrix-sdk-ffi/src
  • crates/matrix-sdk/src/authentication/oauth/qrcode

bindings/matrix-sdk-ffi/src/qr_code.rs

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -610,11 +610,14 @@ pub enum GrantQrLoginProgress {
610610
},
611611
/// The secure channel has been confirmed using the [`CheckCode`] and this
612612
/// device is waiting for the authorization to complete.
613-
WaitingForAuth {
613+
OpeningVerificationUri {
614614
/// A URI to open in a (secure) system browser to verify the new login.
615615
verification_uri: String,
616616
continuation_sender: Arc<ContinuationMessageSender>,
617617
},
618+
WaitingForAuth {
619+
continuation_sender: Arc<ContinuationMessageSender>,
620+
},
618621
/// We are syncing secrets.
619622
SyncingSecrets,
620623
/// The login has successfully finished.
@@ -638,11 +641,15 @@ impl From<qrcode::GrantLoginProgress<QrProgress>> for GrantQrLoginProgress {
638641
check_code_string: format!("{check_code:02}"),
639642
}
640643
}
641-
GrantLoginProgress::Authenticating { verification_uri, continuation_sender } => {
642-
Self::WaitingForAuth {
643-
verification_uri: verification_uri.into(),
644-
continuation_sender: Arc::new(continuation_sender.into()),
645-
}
644+
GrantLoginProgress::OpeningVerificationUri {
645+
verification_uri,
646+
continuation_sender,
647+
} => Self::OpeningVerificationUri {
648+
verification_uri: verification_uri.into(),
649+
continuation_sender: Arc::new(continuation_sender.into()),
650+
},
651+
GrantLoginProgress::WaitingForAuth { continuation_sender } => {
652+
Self::WaitingForAuth { continuation_sender: Arc::new(continuation_sender.into()) }
646653
}
647654
GrantLoginProgress::SyncingSecrets => Self::SyncingSecrets,
648655
GrantLoginProgress::Done => Self::Done,
@@ -659,17 +666,24 @@ pub enum GrantGeneratedQrLoginProgress {
659666
Starting,
660667
/// We have established the secure channel and now need to display the
661668
/// QR code so that the existing device can scan it.
662-
QrReady { qr_code: Arc<QrCodeData> },
669+
QrReady {
670+
qr_code: Arc<QrCodeData>,
671+
},
663672
/// The existing device has scanned the QR code and is displaying the
664673
/// checkcode. We now need to ask the user to enter the checkcode so that
665674
/// we can verify that the channel is indeed secure.
666-
QrScanned { check_code_sender: Arc<CheckCodeSender> },
675+
QrScanned {
676+
check_code_sender: Arc<CheckCodeSender>,
677+
},
667678
/// The secure channel has been confirmed using the [`CheckCode`] and this
668679
/// device is waiting for the authorization to complete.
669-
WaitingForAuth {
680+
OpeningVerificationUri {
670681
/// A URI to open in a (secure) system browser to verify the new login.
671682
verification_uri: String,
672-
continuation_message_sender: Arc<ContinuationMessageSender>,
683+
continuation_sender: Arc<ContinuationMessageSender>,
684+
},
685+
WaitingForAuth {
686+
continuation_sender: Arc<ContinuationMessageSender>,
673687
},
674688
/// We are syncing secrets.
675689
SyncingSecrets,
@@ -694,11 +708,15 @@ impl From<qrcode::GrantLoginProgress<GeneratedQrProgress>> for GrantGeneratedQrL
694708
GrantLoginProgress::EstablishingSecureChannel(GeneratedQrProgress::QrScanned(
695709
inner,
696710
)) => Self::QrScanned { check_code_sender: Arc::new(CheckCodeSender { inner }) },
697-
GrantLoginProgress::Authenticating { verification_uri, continuation_sender } => {
698-
Self::WaitingForAuth {
699-
verification_uri: verification_uri.into(),
700-
continuation_message_sender: Arc::new(continuation_sender.into()),
701-
}
711+
GrantLoginProgress::OpeningVerificationUri {
712+
verification_uri,
713+
continuation_sender,
714+
} => Self::OpeningVerificationUri {
715+
verification_uri: verification_uri.into(),
716+
continuation_sender: Arc::new(continuation_sender.into()),
717+
},
718+
GrantLoginProgress::WaitingForAuth { continuation_sender } => {
719+
Self::WaitingForAuth { continuation_sender: Arc::new(continuation_sender.into()) }
702720
}
703721
GrantLoginProgress::SyncingSecrets => Self::SyncingSecrets,
704722
GrantLoginProgress::Done => Self::Done,

crates/matrix-sdk/src/authentication/oauth/qrcode/grant.rs

Lines changed: 76 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,8 @@ async fn finish_login_grant<Q>(
124124
continuation_sender: ContinuationMessageSender(CloneableSender::new(sender)),
125125
});
126126

127-
// Here we are waiting for the verification URI to be opened?
128-
129-
// We wait for this device to finish up the login in the browser, only then do
130-
// we continue.
127+
// We wait for this device to open the verification URI, this gives the device
128+
// the chance to tell us that it couldn't have opened the verification URI.
131129
match receiver.await {
132130
Ok(ContinuationMessage::Confirm) => {}
133131
// If the user sends an explicit cancellation or the sender is dropped without sending we
@@ -152,13 +150,31 @@ async fn finish_login_grant<Q>(
152150
let message = QrAuthMessage::LoginProtocolAccepted;
153151
channel.send_json(&message).await?;
154152

155-
// TODO: Wait here for what exactly, for the auth to succeed.
156-
157153
// The new device displays the user code it received from the authorization
158154
// server and starts polling for an access token. In parallel, the user
159155
// consents to the new login in the browser on this device, while verifying
160-
// the user code displayed on the other device. -- MSC4108 OAuth 2.0 login
161-
// steps 5 & 6
156+
// the user code displayed on the other device. -- MSC4108 OAuth 2.0 login steps
157+
// 5 & 6
158+
159+
let (sender, receiver) = tokio::sync::oneshot::channel();
160+
state.set(GrantLoginProgress::WaitingForAuth {
161+
continuation_sender: ContinuationMessageSender(CloneableSender::new(sender)),
162+
});
163+
164+
// We wait for this device to confirm that the authorization using the
165+
// verification URI has succeeded.
166+
match receiver.await {
167+
Ok(ContinuationMessage::Confirm) => {}
168+
Ok(ContinuationMessage::Cancel) | Err(_) => {
169+
channel
170+
.send_json(QrAuthMessage::LoginFailure {
171+
reason: LoginFailureReason::UnableToOpenVerificationUri,
172+
homeserver: None,
173+
})
174+
.await?;
175+
return Ok(());
176+
}
177+
}
162178

163179
// We wait for the new device to send us the m.login.success or m.login.failure
164180
// message
@@ -222,13 +238,20 @@ pub enum GrantLoginProgress<Q> {
222238
/// and/or [`CheckCode`].
223239
EstablishingSecureChannel(Q),
224240
/// The secure channel has been confirmed using the [`CheckCode`] and this
225-
/// device is waiting for the authorization to complete.
241+
/// device is waiting for verification URI to be opened.
226242
OpeningVerificationUri {
227243
/// A URI to open in a (secure) system browser to verify the new login.
228244
verification_uri: Url,
229-
/// A sender to confirm that the login has been veriried in the system
230-
/// browser or to cancel because the verification URI couldn't
231-
/// be opened.
245+
/// A sender to confirm that the verification URI has been successfully
246+
/// opened, or cancel if the URI could not have been opened.
247+
continuation_sender: ContinuationMessageSender,
248+
},
249+
/// The verification URI has been opened and the device is waiting for the
250+
/// authorization to complete.
251+
WaitingForAuth {
252+
/// A sender to confirm that the authorization using the verification
253+
/// URI has been completed. We can now wait on the other side to confirm
254+
/// the receival of the access token.
232255
continuation_sender: ContinuationMessageSender,
233256
},
234257
/// The new device has been granted access and this device is sending the
@@ -982,8 +1005,12 @@ mod test {
9821005
assert_eq!(verification_uri.as_str(), verification_uri_complete);
9831006
continuation_sender.confirm().await.expect("should be able to confirm");
9841007
}
985-
GrantLoginProgress::SyncingSecrets => {
1008+
GrantLoginProgress::WaitingForAuth { continuation_sender } => {
9861009
assert_matches!(state, GrantLoginProgress::OpeningVerificationUri { .. });
1010+
continuation_sender.confirm().await.expect("should be able to confirm");
1011+
}
1012+
GrantLoginProgress::SyncingSecrets => {
1013+
assert_matches!(state, GrantLoginProgress::WaitingForAuth { .. });
9871014
}
9881015
GrantLoginProgress::Done => {
9891016
assert_matches!(state, GrantLoginProgress::SyncingSecrets);
@@ -1122,8 +1149,14 @@ mod test {
11221149
assert_eq!(verification_uri.as_str(), verification_uri_complete);
11231150
continuation_sender.confirm().await.expect("should be able to confirm");
11241151
}
1125-
GrantLoginProgress::SyncingSecrets => {
1152+
1153+
GrantLoginProgress::WaitingForAuth { continuation_sender } => {
11261154
assert_matches!(state, GrantLoginProgress::OpeningVerificationUri { .. });
1155+
continuation_sender.confirm().await.expect("should be able to confirm");
1156+
}
1157+
1158+
GrantLoginProgress::SyncingSecrets => {
1159+
assert_matches!(state, GrantLoginProgress::WaitingForAuth { .. });
11271160
}
11281161
GrantLoginProgress::Done => {
11291162
assert_matches!(state, GrantLoginProgress::SyncingSecrets);
@@ -1266,8 +1299,12 @@ mod test {
12661299
assert_eq!(verification_uri.as_str(), verification_uri_complete);
12671300
continuation_sender.confirm().await.expect("should be able to confirm");
12681301
}
1269-
GrantLoginProgress::SyncingSecrets => {
1302+
GrantLoginProgress::WaitingForAuth { continuation_sender } => {
12701303
assert_matches!(state, GrantLoginProgress::OpeningVerificationUri { .. });
1304+
continuation_sender.confirm().await.expect("should be able to confirm");
1305+
}
1306+
GrantLoginProgress::SyncingSecrets => {
1307+
assert_matches!(state, GrantLoginProgress::WaitingForAuth { .. });
12711308
}
12721309
GrantLoginProgress::Done => {
12731310
assert_matches!(state, GrantLoginProgress::SyncingSecrets);
@@ -1900,6 +1937,10 @@ mod test {
19001937
assert_eq!(verification_uri.as_str(), verification_uri_complete);
19011938
continuation_sender.confirm().await.expect("should be able to confirm");
19021939
}
1940+
GrantLoginProgress::WaitingForAuth { continuation_sender } => {
1941+
assert_matches!(state, GrantLoginProgress::OpeningVerificationUri { .. });
1942+
continuation_sender.confirm().await.expect("should be able to confirm");
1943+
}
19031944
_ => {
19041945
panic!("Alice should abort the process");
19051946
}
@@ -2027,6 +2068,10 @@ mod test {
20272068
assert_eq!(verification_uri.as_str(), verification_uri_complete);
20282069
continuation_sender.confirm().await.expect("should be able to confirm");
20292070
}
2071+
GrantLoginProgress::WaitingForAuth { continuation_sender } => {
2072+
assert_matches!(state, GrantLoginProgress::OpeningVerificationUri { .. });
2073+
continuation_sender.confirm().await.expect("should be able to confirm");
2074+
}
20302075
_ => {
20312076
panic!("Alice should abort the process");
20322077
}
@@ -2570,6 +2615,10 @@ mod test {
25702615
assert_eq!(verification_uri.as_str(), verification_uri_complete);
25712616
continuation_sender.confirm().await.expect("should be able to confirm");
25722617
}
2618+
GrantLoginProgress::WaitingForAuth { continuation_sender } => {
2619+
assert_matches!(state, GrantLoginProgress::OpeningVerificationUri { .. });
2620+
continuation_sender.confirm().await.expect("should be able to confirm");
2621+
}
25732622
_ => {
25742623
panic!("Alice should abort the process");
25752624
}
@@ -2702,6 +2751,10 @@ mod test {
27022751
assert_eq!(verification_uri.as_str(), verification_uri_complete);
27032752
continuation_sender.confirm().await.expect("should be able to confirm");
27042753
}
2754+
GrantLoginProgress::WaitingForAuth { continuation_sender } => {
2755+
assert_matches!(state, GrantLoginProgress::OpeningVerificationUri { .. });
2756+
continuation_sender.confirm().await.expect("should be able to confirm");
2757+
}
27052758
_ => {
27062759
panic!("Alice should abort the process");
27072760
}
@@ -2853,6 +2906,10 @@ mod test {
28532906
assert_eq!(verification_uri.as_str(), verification_uri_complete);
28542907
continuation_sender.confirm().await.expect("should be able to confirm");
28552908
}
2909+
GrantLoginProgress::WaitingForAuth { continuation_sender } => {
2910+
assert_matches!(state, GrantLoginProgress::OpeningVerificationUri { .. });
2911+
continuation_sender.confirm().await.expect("should be able to confirm");
2912+
}
28562913
_ => {
28572914
panic!("Alice should abort the process");
28582915
}
@@ -2986,6 +3043,10 @@ mod test {
29863043
assert_eq!(verification_uri.as_str(), verification_uri_complete);
29873044
continuation_sender.confirm().await.expect("should be able to confirm");
29883045
}
3046+
GrantLoginProgress::WaitingForAuth { continuation_sender } => {
3047+
assert_matches!(state, GrantLoginProgress::OpeningVerificationUri { .. });
3048+
continuation_sender.confirm().await.expect("should be able to confirm");
3049+
}
29893050
_ => {
29903051
panic!("Alice should abort the process");
29913052
}

0 commit comments

Comments
 (0)