automatically refresh access token to avoid prompting to log in (#221)

This commit is contained in:
Carson McManus 2023-06-24 13:18:22 -04:00 committed by GitHub
parent 64697b6808
commit bff16bd341
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 66 additions and 3 deletions

View file

@ -6,11 +6,13 @@ use std::{
path::Path, path::Path,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use steamguard::protobufs::steammessages_auth_steamclient::{ use steamguard::{
EAuthSessionGuardType, EAuthTokenPlatformType, protobufs::steammessages_auth_steamclient::{EAuthSessionGuardType, EAuthTokenPlatformType},
refresher::TokenRefresher,
transport::WebApiTransport,
}; };
use steamguard::token::Tokens;
use steamguard::{steamapi, DeviceDetails, LoginError, SteamGuardAccount, UserLogin}; use steamguard::{steamapi, DeviceDetails, LoginError, SteamGuardAccount, UserLogin};
use steamguard::{steamapi::AuthenticationClient, token::Tokens};
use crate::accountmanager::migrate::load_and_migrate; use crate::accountmanager::migrate::load_and_migrate;
pub use crate::accountmanager::{AccountManager, ManifestAccountLoadError, ManifestLoadError}; pub use crate::accountmanager::{AccountManager, ManifestAccountLoadError, ManifestLoadError};
@ -219,6 +221,25 @@ fn get_selected_accounts(
} }
fn do_login(account: &mut SteamGuardAccount) -> anyhow::Result<()> { 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() { if !account.account_name.is_empty() {
info!("Username: {}", account.account_name); info!("Username: {}", account.account_name);
} else { } else {

View file

@ -30,6 +30,7 @@ pub mod accountlinker;
mod api_responses; mod api_responses;
mod confirmation; mod confirmation;
pub mod protobufs; pub mod protobufs;
pub mod refresher;
mod secret_string; mod secret_string;
pub mod steamapi; pub mod steamapi;
pub mod token; pub mod token;

View file

@ -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<WebApiTransport>,
}
impl TokenRefresher {
pub fn new(client: AuthenticationClient<WebApiTransport>) -> Self {
Self { client }
}
pub fn refresh(&mut self, steam_id: u64, tokens: &Tokens) -> Result<Jwt, anyhow::Error> {
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())
}
}

View file

@ -102,6 +102,10 @@ impl Tokens {
&self.access_token &self.access_token
} }
pub fn set_access_token(&mut self, token: Jwt) {
self.access_token = token;
}
pub fn refresh_token(&self) -> &Jwt { pub fn refresh_token(&self) -> &Jwt {
&self.refresh_token &self.refresh_token
} }