summaryrefslogtreecommitdiffstats
path: root/ozone/src/auth.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ozone/src/auth.rs')
-rw-r--r--ozone/src/auth.rs43
1 files changed, 33 insertions, 10 deletions
diff --git a/ozone/src/auth.rs b/ozone/src/auth.rs
index ca06e93..9b934cd 100644
--- a/ozone/src/auth.rs
+++ b/ozone/src/auth.rs
@@ -15,6 +15,7 @@ pub use types::*;
use crate::auth::error::{AuthError, AuthErrorKind};
use self::msa::{XSTS_RP_MINECRAFT_SERVICES, XSTS_RP_XBOX_LIVE};
use crate::util;
+use crate::util::progress::{Step, StepProgress};
impl Token {
fn is_expired(&self, now: DateTime<Utc>) -> bool {
@@ -72,7 +73,7 @@ impl MsaAccount {
// logs into xbox live using a refresh token
// (panics if no refresh token present)
- async fn xbl_login_refresh(&mut self, client: &reqwest::Client) -> Result<(), AuthError> {
+ async fn xbl_login_refresh(&mut self, client: &reqwest::Client, xbl_login: Step<'_, '_>) -> Result<(), AuthError> {
debug!("Using refresh token for XBL login");
let oauth_client = create_oauth_client!(self.is_azure_client_id, self.client_id.clone());
let refresh_token = self.refresh_token.as_ref().expect("refresh_access_token called with no refresh token");
@@ -80,7 +81,6 @@ impl MsaAccount {
let tokenres: BasicTokenResponse = oauth_client
.exchange_refresh_token(refresh_token)
.add_scopes(self.scopes_iter())
- .add_extra_param("response_type", "device_code")
.request_async(client)
.await.map_err(|e| match e {
RequestTokenError::ServerResponse(res)
@@ -91,6 +91,7 @@ impl MsaAccount {
self.refresh_token = tokenres.refresh_token().cloned();
+ xbl_login.make_current();
self.xbl_login(client, tokenres.access_token()).await
}
@@ -124,7 +125,7 @@ impl MsaAccount {
// - check if the XBL token is valid/not expired
// - if it is expired, try to use refresh token to get a new one
// - get rid of auth token if yeah
- async fn ensure_xbl(&mut self, client: &reqwest::Client, now: DateTime<Utc>) -> Result<(), AuthError> {
+ async fn ensure_xbl<'p>(&mut self, client: &reqwest::Client, now: DateTime<Utc>, xbl_refresh_step: Step<'p, '_>, xbl_login_step: Step<'p, '_>) -> Result<(), AuthError> {
if self.xbl_token.as_ref().is_some_and(|tok| !tok.is_expired(now)) {
debug!("XBL token valid. Using it.");
return Ok(())
@@ -135,7 +136,8 @@ impl MsaAccount {
}
debug!("XBL token expired. Trying to refresh it.");
- self.xbl_login_refresh(client).await?;
+ xbl_refresh_step.make_current();
+ self.xbl_login_refresh(client, xbl_login_step).await?;
self.mc_token = None;
@@ -146,12 +148,13 @@ impl MsaAccount {
// - if the minecraft services token invalid/expired/missing, do the following
// - get minecraftservices xsts token
// - use minecraftservices to get mojang token with that xsts token
- async fn ensure_mc_token(&mut self, client: &reqwest::Client, now: DateTime<Utc>) -> Result<(), AuthError> {
+ async fn ensure_mc_token<'p>(&mut self, client: &reqwest::Client, now: DateTime<Utc>, xsts_step: Step<'p, '_>, login_step: Step<'p, '_>) -> Result<(), AuthError> {
if self.mc_token.as_ref().is_some_and(|tok| !tok.is_expired(now)) {
debug!("Mojang token valid. Using it.");
return Ok(())
}
+ xsts_step.make_current();
debug!("Mojang token has expired. Must log in again.");
let xbl_token = self.xbl_token.as_ref().expect("ensure_mc_token requires xbl token").value.as_str();
let (user_hash, mc_xsts_tok) = match msa::xsts_request(client, xbl_token, XSTS_RP_MINECRAFT_SERVICES).await? {
@@ -163,6 +166,7 @@ impl MsaAccount {
msa::XSTSAuthResponse::Error(e) => return Err(e.into())
};
+ login_step.make_current();
debug!("Got MinecraftServices XSTS, logging in.");
self.mc_token = Some(mcservices::login_with_xbox(client, mc_xsts_tok.as_str(), user_hash.as_str()).await?);
@@ -190,18 +194,23 @@ impl MsaAccount {
Ok(())
}
- async fn load_profile(&mut self, client: &reqwest::Client) -> Result<(), AuthError> {
+ async fn load_profile(&mut self, client: &reqwest::Client, steps: [Step<'_, '_>; 4]) -> Result<(), AuthError> {
+ steps[0].make_current();
self.load_xbox_info(client).await?;
let mc_token = self.mc_token.as_ref().expect("minecraft token missing").value.as_str();
+ steps[1].make_current();
debug!("Checking if you own the game...");
if !mcservices::owns_the_game(client, mc_token).await? {
return Err(AuthErrorKind::NotEntitled.into());
}
debug!("Getting your profile info...");
+ steps[2].make_current();
let player_info = mcservices::get_player_info(client, mc_token).await?;
+
+ steps[3].make_current();
let player_profile = mcservices::get_player_profile(client, player_info.id).await
.map_err(|e| AuthError::internal_msg_src("looking up profile", e))?;
@@ -211,14 +220,28 @@ impl MsaAccount {
Ok(())
}
- pub async fn log_in_silent(&mut self, client: &reqwest::Client) -> Result<(), AuthError> {
+ pub async fn log_in_silent(&mut self, client: &reqwest::Client, progress: &dyn util::progress::ProgressIndication) -> Result<(), AuthError> {
+ let steps = StepProgress::from(progress);
+ let step_login = steps.step("Attempt non-interactive login");
+ let step_xbl_refresh = steps.step("Refresh Xbox Live token");
+ let step_xbl_login = steps.step("Log into Xbox Live");
+ let step_mc_xsts = steps.step("Request Minecraft XSTS token");
+ let step_mcs_login = steps.step("Log into Minecraft");
+ let step_xbl_profile = steps.step("Retrieve your Xbox profile");
+ let step_mc_entitlement = steps.step("Check if you own Minecraft");
+ let step_mc_profile_1 = steps.step("Look up your Minecraft profile (1)");
+ let step_mc_profile_2 = steps.step("Look up your Minecraft profile (2)");
+ steps.update_max();
+
+ step_login.make_current();
+
// see it's kind of funny that I call this variable "now" despite the fact that it's
// unconditionally 12 hours in the future - figboot
let now = Utc::now() + TimeDelta::hours(12);
- self.ensure_xbl(client, now).await?;
- self.ensure_mc_token(client, now).await?;
- self.load_profile(client).await?;
+ self.ensure_xbl(client, now, step_xbl_refresh, step_xbl_login).await?;
+ self.ensure_mc_token(client, now, step_mc_xsts, step_mcs_login).await?;
+ self.load_profile(client, [step_xbl_profile, step_mc_entitlement, step_mc_profile_1, step_mc_profile_2]).await?;
Ok(())
}