Skip to content

Commit 62e1209

Browse files
authored
Decode OTP Uri before parsing (#551)
Fixes an issue #548 on issuer and label parsing.
2 parents 01c8e2b + f5f974d commit 62e1209

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

src/otp/from_otp_uri.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ pub trait FromOtpUri: Sized {
99

1010
impl FromOtpUri for OTPElement {
1111
fn from_otp_uri(otp_uri: &str) -> color_eyre::Result<Self> {
12-
let parsed_uri = Url::parse(otp_uri).map_err(ErrReport::from)?;
12+
let decoded = urlencoding::decode(otp_uri).map_err(ErrReport::from)?;
13+
let parsed_uri = Url::parse(&decoded).map_err(ErrReport::from)?;
1314

1415
let otp_type = parsed_uri
1516
.host_str()

src/otp/otp_element.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,4 +423,34 @@ mod test {
423423
result.unwrap_err().to_string()
424424
);
425425
}
426+
427+
#[test]
428+
fn gh_issue_548_invalid_otp_uri_label_url_encoded() {
429+
// Arrange
430+
let otp_uri = "otpauth://totp/foo%3abar?issuer=foo&secret=JBSWY3DPEHPK3PXP";
431+
432+
// Act
433+
let result = OTPElement::from_otp_uri(otp_uri);
434+
435+
// Assert
436+
assert!(result.is_ok());
437+
let actual = result.unwrap();
438+
assert_eq!("foo", actual.issuer.as_str());
439+
assert_eq!("bar", actual.label.as_str());
440+
}
441+
442+
#[test]
443+
fn gh_issue_548_invalid_otp_uri_label_non_url_encoded() {
444+
// Arrange
445+
let otp_uri = "otpauth://totp/foo:bar?issuer=foo&secret=JBSWY3DPEHPK3PXP";
446+
447+
// Act
448+
let result = OTPElement::from_otp_uri(otp_uri);
449+
450+
// Assert
451+
assert!(result.is_ok());
452+
let actual = result.unwrap();
453+
assert_eq!("foo", actual.issuer.as_str());
454+
assert_eq!("bar", actual.label.as_str());
455+
}
426456
}

0 commit comments

Comments
 (0)