Merge pull request #22 from constantoine/21-bug-issuer-error
Fix url related bugs
This commit is contained in:
commit
181d17edcc
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "totp-rs"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
authors = ["Cleo Rebert <cleo.rebert@gmail.com>"]
|
||||
edition = "2021"
|
||||
readme = "README.md"
|
||||
|
@ -12,11 +12,11 @@ keywords = ["authentication", "2fa", "totp", "hmac", "otp"]
|
|||
categories = ["authentication", "web-programming"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = [ "qr", "serde_support" ]
|
||||
features = [ "qr", "serde_support", "otpauth" ]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
otpauth = ["url"]
|
||||
otpauth = ["url", "urlencoding"]
|
||||
qr = ["qrcodegen", "image", "base64", "otpauth"]
|
||||
serde_support = ["serde"]
|
||||
|
||||
|
@ -26,7 +26,8 @@ sha2 = "~0.10.2"
|
|||
sha-1 = "~0.10.0"
|
||||
hmac = "~0.12.1"
|
||||
base32 = "~0.4"
|
||||
url = { version = "2.2.2", optional = true }
|
||||
urlencoding = { version = "^2.1.0", optional = true}
|
||||
url = { version = "^2.2.2", optional = true }
|
||||
constant_time_eq = "~0.2.1"
|
||||
qrcodegen = { version = "~1.8", optional = true }
|
||||
image = { version = "~0.24.2", features = ["png"], optional = true, default-features = false}
|
||||
|
|
41
src/lib.rs
41
src/lib.rs
|
@ -57,6 +57,8 @@ use {base64, image::Luma, qrcodegen};
|
|||
|
||||
#[cfg(feature = "otpauth")]
|
||||
use url::{Host, ParseError, Url};
|
||||
#[cfg(feature = "otpauth")]
|
||||
use urlencoding;
|
||||
|
||||
use hmac::Mac;
|
||||
use std::time::{SystemTime, SystemTimeError, UNIX_EPOCH};
|
||||
|
@ -280,16 +282,18 @@ impl<T: AsRef<[u8]>> TOTP<T> {
|
|||
let mut step = 30;
|
||||
let mut secret = Vec::new();
|
||||
let mut issuer: Option<String> = None;
|
||||
let account_name: String;
|
||||
let mut account_name: String;
|
||||
|
||||
let path = url.path();
|
||||
let path = url.path().trim_start_matches('/');
|
||||
if path.contains(':') {
|
||||
let parts = path.split_once(':').unwrap();
|
||||
issuer = Some(parts.0.to_owned());
|
||||
issuer = Some(urlencoding::decode(parts.0.to_owned().as_str()).map_err(|_| TotpUrlError::Issuer)?.to_string());
|
||||
account_name = parts.1.trim_start_matches(':').to_owned();
|
||||
} else {
|
||||
account_name = path.to_owned();
|
||||
}
|
||||
|
||||
account_name = urlencoding::decode(account_name.as_str()).map_err(|_| TotpUrlError::AccountName)?.to_string();
|
||||
|
||||
for (key, value) in url.query_pairs() {
|
||||
match key.as_ref() {
|
||||
|
@ -343,9 +347,9 @@ impl<T: AsRef<[u8]>> TOTP<T> {
|
|||
#[cfg(feature = "otpauth")]
|
||||
pub fn get_url(&self) -> String {
|
||||
let label: String;
|
||||
let account_name: String = url::form_urlencoded::byte_serialize(self.account_name.as_bytes()).collect();
|
||||
let account_name: String = urlencoding::encode(self.account_name.as_str()).to_string();
|
||||
if self.issuer.is_some() {
|
||||
let issuer: String = url::form_urlencoded::byte_serialize(self.issuer.as_ref().unwrap().as_bytes()).collect();
|
||||
let issuer: String = urlencoding::encode(self.issuer.as_ref().unwrap().as_str()).to_string();
|
||||
label = format!("{0}:{1}?issuer={0}&", issuer, account_name);
|
||||
} else {
|
||||
label = format!("{}?", account_name);
|
||||
|
@ -633,6 +637,33 @@ mod tests {
|
|||
assert_eq!(totp.step, 60);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "otpauth")]
|
||||
fn from_url_to_url() {
|
||||
let totp = TOTP::<Vec<u8>>::from_url("otpauth://totp/Github:constantoine%40github.com?issuer=Github&secret=KRSXG5CTMVRXEZLU&digits=6&algorithm=SHA1").unwrap();
|
||||
let totp_bis = TOTP::new(Algorithm::SHA1, 6, 1, 1, "TestSecret", Some("Github".to_string()), "constantoine@github.com".to_string()).unwrap();
|
||||
assert_eq!(totp.get_url(), totp_bis.get_url());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "otpauth")]
|
||||
fn from_url_issuer_special() {
|
||||
let totp = TOTP::<Vec<u8>>::from_url("otpauth://totp/Github%40:constantoine%40github.com?issuer=Github%40&secret=KRSXG5CTMVRXEZLU&digits=6&algorithm=SHA1").unwrap();
|
||||
let totp_bis = TOTP::new(Algorithm::SHA1, 6, 1, 1, "TestSecret", Some("Github@".to_string()), "constantoine@github.com".to_string()).unwrap();
|
||||
assert_eq!(totp.get_url(), totp_bis.get_url());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "otpauth")]
|
||||
fn from_url_query_issuer() {
|
||||
let totp = TOTP::<Vec<u8>>::from_url("otpauth://totp/GitHub:test?issuer=GitHub&secret=ABC&digits=8&period=60&algorithm=SHA256").unwrap();
|
||||
assert_eq!(totp.secret, base32::decode(base32::Alphabet::RFC4648 { padding: false }, "ABC").unwrap());
|
||||
assert_eq!(totp.algorithm, Algorithm::SHA256);
|
||||
assert_eq!(totp.digits, 8);
|
||||
assert_eq!(totp.skew, 1);
|
||||
assert_eq!(totp.step, 60);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "otpauth")]
|
||||
fn from_url_query_different_issuers() {
|
||||
|
|
Loading…
Reference in New Issue