From bff16bd341c53b037857c9e0621b8c7b3074792d Mon Sep 17 00:00:00 2001 From: Carson McManus Date: Sat, 24 Jun 2023 13:18:22 -0400 Subject: [PATCH] automatically refresh access token to avoid prompting to log in (#221) --- src/main.rs | 27 ++++++++++++++++++++++++--- steamguard/src/lib.rs | 1 + steamguard/src/refresher.rs | 37 +++++++++++++++++++++++++++++++++++++ steamguard/src/token.rs | 4 ++++ 4 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 steamguard/src/refresher.rs diff --git a/src/main.rs b/src/main.rs index ddb9bf4..6884ab3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,11 +6,13 @@ use std::{ path::Path, sync::{Arc, Mutex}, }; -use steamguard::protobufs::steammessages_auth_steamclient::{ - EAuthSessionGuardType, EAuthTokenPlatformType, +use steamguard::{ + protobufs::steammessages_auth_steamclient::{EAuthSessionGuardType, EAuthTokenPlatformType}, + refresher::TokenRefresher, + transport::WebApiTransport, }; -use steamguard::token::Tokens; use steamguard::{steamapi, DeviceDetails, LoginError, SteamGuardAccount, UserLogin}; +use steamguard::{steamapi::AuthenticationClient, token::Tokens}; use crate::accountmanager::migrate::load_and_migrate; pub use crate::accountmanager::{AccountManager, ManifestAccountLoadError, ManifestLoadError}; @@ -219,6 +221,25 @@ fn get_selected_accounts( } fn do_login(account: &mut SteamGuardAccount) -> anyhow::Result<()> { + if let Some(tokens) = account.tokens.as_mut() { + info!("Refreshing access token..."); + let client = AuthenticationClient::new(WebApiTransport::new()); + let mut refresher = TokenRefresher::new(client); + match refresher.refresh(account.steam_id, tokens) { + Ok(token) => { + info!("Successfully refreshed access token, no need to prompt to log in."); + tokens.set_access_token(token); + return Ok(()); + } + Err(err) => { + warn!( + "Failed to refresh access token, prompting for login: {}", + err + ); + } + } + } + if !account.account_name.is_empty() { info!("Username: {}", account.account_name); } else { diff --git a/steamguard/src/lib.rs b/steamguard/src/lib.rs index 8200292..d2155bb 100644 --- a/steamguard/src/lib.rs +++ b/steamguard/src/lib.rs @@ -30,6 +30,7 @@ pub mod accountlinker; mod api_responses; mod confirmation; pub mod protobufs; +pub mod refresher; mod secret_string; pub mod steamapi; pub mod token; diff --git a/steamguard/src/refresher.rs b/steamguard/src/refresher.rs new file mode 100644 index 0000000..aad5205 --- /dev/null +++ b/steamguard/src/refresher.rs @@ -0,0 +1,37 @@ +use crate::{ + protobufs::steammessages_auth_steamclient::CAuthentication_AccessToken_GenerateForApp_Request, + steamapi::{AuthenticationClient, EResult}, + token::{Jwt, Tokens}, + transport::WebApiTransport, +}; + +pub struct TokenRefresher { + client: AuthenticationClient, +} + +impl TokenRefresher { + pub fn new(client: AuthenticationClient) -> Self { + Self { client } + } + + pub fn refresh(&mut self, steam_id: u64, tokens: &Tokens) -> Result { + let mut req = CAuthentication_AccessToken_GenerateForApp_Request::new(); + req.set_steamid(steam_id); + req.set_refresh_token(tokens.refresh_token().expose_secret().to_owned()); + + let resp = self + .client + .generate_access_token(req, tokens.access_token())?; + + if resp.result != EResult::OK { + return Err(anyhow::anyhow!( + "Failed to refresh access token: {:?}", + resp.result + )); + } + + let mut resp = resp.into_response_data(); + + Ok(resp.take_access_token().into()) + } +} diff --git a/steamguard/src/token.rs b/steamguard/src/token.rs index 778ca41..931567b 100644 --- a/steamguard/src/token.rs +++ b/steamguard/src/token.rs @@ -102,6 +102,10 @@ impl Tokens { &self.access_token } + pub fn set_access_token(&mut self, token: Jwt) { + self.access_token = token; + } + pub fn refresh_token(&self) -> &Jwt { &self.refresh_token }