From 677f114ed2a4010bd85a51f1f6b10b5d7eabe7c8 Mon Sep 17 00:00:00 2001 From: tuxuser <462620+tuxuser@users.noreply.github.com> Date: Thu, 21 Dec 2023 09:52:50 +0100 Subject: [PATCH] tokens: Implement validity check, define token lifetimes as DateTime (instead of string) --- examples/src/bin/auth_minecraft.rs | 1 + examples/src/bin/xbl_signed_request.rs | 1 + src/error.rs | 4 ++++ src/lib.rs | 2 +- src/models.rs | 22 ++++++++++++++++++---- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/examples/src/bin/auth_minecraft.rs b/examples/src/bin/auth_minecraft.rs index a303521..88d44a9 100644 --- a/examples/src/bin/auth_minecraft.rs +++ b/examples/src/bin/auth_minecraft.rs @@ -29,6 +29,7 @@ async fn main() -> Result<(), Error> { ) .await?; + xsts_mc_services.check_validity()?; let identity_token = xsts_mc_services.authorization_header_value(); println!("identityToken: {identity_token}"); diff --git a/examples/src/bin/xbl_signed_request.rs b/examples/src/bin/xbl_signed_request.rs index 33e9bcc..3c1a27c 100644 --- a/examples/src/bin/xbl_signed_request.rs +++ b/examples/src/bin/xbl_signed_request.rs @@ -23,6 +23,7 @@ async fn main() -> Result<(), Box> { let xsts_token = token_store .authorization_token .ok_or(Error::GeneralError("No XSTS token was acquired".into()))?; + xsts_token.check_validity()?; // Send a http request // Request will get signed and MS-CV header populated diff --git a/src/error.rs b/src/error.rs index 9d8dd80..495574d 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,6 +1,7 @@ //! Definition of custom error type. //! +use chrono::{DateTime, Utc}; use oauth2::{ basic::BasicErrorResponse, reqwest::AsyncHttpClientError, DeviceCodeErrorResponse, RequestTokenError, @@ -65,6 +66,9 @@ pub enum Error { /// Failed processing HTTP request #[error("Failed processing HTTP request")] InvalidRequest(String), + /// Token expired + #[error("Token expired")] + TokenExpired(DateTime), /// Unknown error #[error("unknown xal error")] Unknown, diff --git a/src/lib.rs b/src/lib.rs index 90fa309..7ba688b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,7 +33,7 @@ //! &mut authenticator, //! CliCallbackHandler //! ).await?; -//! +//! //! // User will be prompted on commandline to proceed with authentication //! //! token_store.update_timestamp(); diff --git a/src/models.rs b/src/models.rs index df2e131..62c0bd3 100644 --- a/src/models.rs +++ b/src/models.rs @@ -245,9 +245,12 @@ pub mod request { /// HTTP Response models pub mod response { + use chrono::{DateTime, TimeZone, Utc}; use oauth2::basic::BasicTokenResponse; use url::Url; + use crate::Error; + use super::{Deserialize, HashMap, Serialize, SigningPolicy}; /// Alias type for Windows Live token response @@ -296,9 +299,9 @@ pub mod response { #[serde(rename_all = "PascalCase")] pub struct XTokenResponse { /// Issue datetime of token - pub issue_instant: String, + pub issue_instant: DateTime, /// Expiry datetime of token - pub not_after: String, + pub not_after: DateTime, /// Token value pub token: String, /// XSTS display claims @@ -322,14 +325,25 @@ pub mod response { impl From<&str> for XTokenResponse { fn from(s: &str) -> Self { Self { - issue_instant: "2020-12-15T00:00:00.0000000Z".into(), - not_after: "2199-12-15T00:00:00.0000000Z".into(), + issue_instant: Utc.with_ymd_and_hms(2020, 12, 15, 0, 0, 0).unwrap(), + not_after: Utc.with_ymd_and_hms(2199, 12, 15, 0, 0, 0).unwrap(), token: s.to_owned(), display_claims: None, } } } + impl XTokenResponse { + /// Check if token is valid + pub fn check_validity(&self) -> Result<(), Error> { + if self.not_after < chrono::offset::Utc::now() { + return Err(Error::TokenExpired(self.not_after)); + } + + Ok(()) + } + } + /// Sisu authentication repsonse #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "PascalCase")]