feat: revoke OAuth token when logging out
This commit is contained in:
parent
d452af4fb7
commit
62f8a9210c
2 changed files with 70 additions and 7 deletions
|
|
@ -193,6 +193,8 @@ enum Commands {
|
|||
Vdata,
|
||||
/// Log in using your Google account
|
||||
Login,
|
||||
/// Log out from your Google account
|
||||
Logout,
|
||||
}
|
||||
|
||||
#[derive(Default, Copy, Clone, ValueEnum)]
|
||||
|
|
@ -1226,6 +1228,10 @@ async fn run() -> anyhow::Result<()> {
|
|||
}
|
||||
anstream::println!("{}", "Logged in.".green());
|
||||
}
|
||||
Commands::Logout => {
|
||||
rp.user_auth_logout().await?;
|
||||
anstream::println!("{}", "Logged out.".red());
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1233,7 +1233,7 @@ impl RustyPipe {
|
|||
pub async fn user_auth_check_login(&self) -> Result<(), Error> {
|
||||
let cache_token = self.inner.cache.oauth_token.read().unwrap().clone();
|
||||
if let Some(token) = cache_token {
|
||||
let token = self.refresh_token(&token.refresh_token).await?;
|
||||
let token = self.user_auth_refresh_token(&token.refresh_token).await?;
|
||||
{
|
||||
let mut cache_token = self.inner.cache.oauth_token.write().unwrap();
|
||||
*cache_token = Some(token.clone());
|
||||
|
|
@ -1256,7 +1256,57 @@ impl RustyPipe {
|
|||
}
|
||||
|
||||
/// Log out the user and remove the OAuth token from the cache
|
||||
pub async fn user_auth_logout(&self) {
|
||||
pub async fn user_auth_logout(&self) -> Result<(), Error> {
|
||||
#[derive(Serialize)]
|
||||
struct RevokeRequest<'a> {
|
||||
token: &'a str,
|
||||
}
|
||||
|
||||
let cache_token = self
|
||||
.inner
|
||||
.cache
|
||||
.oauth_token
|
||||
.read()
|
||||
.unwrap()
|
||||
.clone()
|
||||
.ok_or(Error::Auth(AuthError::NoLogin))?;
|
||||
let revoke_request = RevokeRequest {
|
||||
token: &cache_token.refresh_token,
|
||||
};
|
||||
|
||||
let resp = self
|
||||
.inner
|
||||
.http
|
||||
.post("https://www.youtube.com/o/oauth2/revoke")
|
||||
.header(header::USER_AGENT, TV_UA)
|
||||
.header(header::ORIGIN, YOUTUBE_HOME_URL)
|
||||
.header(header::REFERER, YOUTUBE_TV_URL)
|
||||
.json(&revoke_request)
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
if let Err(estatus) = resp.error_for_status_ref().map(|_| ()) {
|
||||
if let Ok(OauthTokenResponse::Error {
|
||||
error,
|
||||
error_description,
|
||||
}) = resp.json::<OauthTokenResponse>().await
|
||||
{
|
||||
// User is already logged out
|
||||
if error == "invalid_token" {
|
||||
tracing::info!("user already logged out ({error}: {error_description})");
|
||||
} else {
|
||||
return Err(Error::Other(format!("{error}: {error_description}").into()));
|
||||
}
|
||||
} else {
|
||||
return Err(estatus.into());
|
||||
}
|
||||
}
|
||||
self.user_auth_remove_token().await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove the stored OAuth token from the cache
|
||||
async fn user_auth_remove_token(&self) {
|
||||
{
|
||||
let mut cache_token = self.inner.cache.oauth_token.write().unwrap();
|
||||
*cache_token = None;
|
||||
|
|
@ -1264,7 +1314,8 @@ impl RustyPipe {
|
|||
self.store_cache().await;
|
||||
}
|
||||
|
||||
async fn refresh_token(&self, refresh_token: &str) -> Result<OauthToken, Error> {
|
||||
/// Obtain a new OAuth token using the given refresh token
|
||||
async fn user_auth_refresh_token(&self, refresh_token: &str) -> Result<OauthToken, Error> {
|
||||
tracing::debug!("refreshing OAuth token");
|
||||
|
||||
let token_request = OauthTokenRequest {
|
||||
|
|
@ -1296,9 +1347,15 @@ impl RustyPipe {
|
|||
OauthTokenResponse::Error {
|
||||
error,
|
||||
error_description,
|
||||
} => Err(Error::Auth(AuthError::Refresh(format!(
|
||||
"{error}: {error_description}"
|
||||
)))),
|
||||
} => {
|
||||
// If the token is expired or revoked, remove it from the client
|
||||
if error == "invalid_grant" {
|
||||
self.user_auth_remove_token().await;
|
||||
}
|
||||
Err(Error::Auth(AuthError::Refresh(format!(
|
||||
"{error}: {error_description}"
|
||||
))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1307,7 +1364,7 @@ impl RustyPipe {
|
|||
let cache_token = self.inner.cache.oauth_token.read().unwrap().clone();
|
||||
if let Some(token) = cache_token {
|
||||
if token.expires_at < (OffsetDateTime::now_utc() + Duration::from_secs(60)) {
|
||||
let token = self.refresh_token(&token.refresh_token).await?;
|
||||
let token = self.user_auth_refresh_token(&token.refresh_token).await?;
|
||||
let access_token = token.access_token.to_owned();
|
||||
|
||||
{
|
||||
|
|
|
|||
Reference in a new issue