From ff8b3ede308d6660c058e93aae27073ebea31ff1 Mon Sep 17 00:00:00 2001 From: Mark Catley Date: Wed, 26 Jun 2019 21:35:23 +1200 Subject: [PATCH] Updates to allow retrieving a token using the device flow on Salesforce. --- src/device.rs | 16 +++++++++++----- src/types.rs | 23 ++++++++++++++--------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/device.rs b/src/device.rs index c4b60df..2beaaea 100644 --- a/src/device.rs +++ b/src/device.rs @@ -218,12 +218,17 @@ where return Err(RequestError::ClientError(err)); } Ok(res) => { + // This return type is defined in https://tools.ietf.org/html/draft-ietf-oauth-device-flow-15#section-3.2 + // The alias is present as Google use a non-standard name for verification_uri. + // According to the standard interval is optional, however, all tested implementations provide it. + // verification_uri_complete is optional in the standard but not provided in tested implementations. #[derive(Deserialize)] struct JsonData { device_code: String, user_code: String, - verification_url: String, - expires_in: i64, + #[serde(alias = "verification_url")] + verification_uri: String, + expires_in: Option, interval: i64, } @@ -242,11 +247,12 @@ where let decoded: JsonData = json::from_str(&json_str).unwrap(); + let expires_in = decoded.expires_in.unwrap_or(60 * 60); + let pi = PollInformation { user_code: decoded.user_code, - verification_url: decoded.verification_url, - expires_at: Utc::now() - + chrono::Duration::seconds(decoded.expires_in), + verification_url: decoded.verification_uri, + expires_at: Utc::now() + chrono::Duration::seconds(expires_in), interval: Duration::from_secs(i64::abs(decoded.interval) as u64), }; Ok((pi, decoded.device_code)) diff --git a/src/types.rs b/src/types.rs index a4d200e..f4d6797 100644 --- a/src/types.rs +++ b/src/types.rs @@ -292,16 +292,18 @@ impl Token { if self.access_token.len() == 0 { panic!("called expired() on unset token"); } - self.expiry_date() - chrono::Duration::minutes(1) <= Utc::now() + if let Some(expiry_date) = self.expiry_date() { + expiry_date - chrono::Duration::minutes(1) <= Utc::now() + } else { + false + } } /// Returns a DateTime object representing our expiry date. - pub fn expiry_date(&self) -> DateTime { - Utc.timestamp( - self.expires_in_timestamp - .expect("Tokens without an absolute expiry are invalid"), - 0, - ) + pub fn expiry_date(&self) -> Option> { + let expires_in_timestamp = self.expires_in_timestamp?; + + Utc.timestamp(expires_in_timestamp, 0).into() } /// Adjust our stored expiry format to be absolute, using the current time. @@ -311,8 +313,11 @@ impl Token { return self; } - self.expires_in_timestamp = Some(Utc::now().timestamp() + self.expires_in.unwrap()); - self.expires_in = None; + if let Some(expires_in) = self.expires_in { + self.expires_in_timestamp = Some(Utc::now().timestamp() + expires_in); + self.expires_in = None; + } + self } }