diff --git a/src/lib.rs b/src/lib.rs index 1e930b4..9f4ca64 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,7 +56,7 @@ use std::fmt::Debug; use getset::{CopyGetters, Getters}; use nutype::nutype; -use reqwest::Client; +use reqwest::{Client, StatusCode}; use serde::{Deserialize, Serialize}; use serde_json::json; use thiserror::Error; @@ -92,6 +92,14 @@ pub enum MinecraftAuthorizationError { #[error(transparent)] Reqwest(#[from] reqwest::Error), + /// Account belongs to a minor who needs to be added to a microsoft family + #[error("Minor must be added to microsoft family")] + AddToFamily, + + /// Account does not have xbox, user must create an xbox account to continue + #[error("Account does not have xbox")] + NoXbox, + /// Claims were missing from the response #[error("missing claims from response")] MissingClaims, @@ -131,6 +139,25 @@ struct XboxLiveAuthenticationResponse { display_claims: HashMap>>, } +/// The error response from Xbox when authenticating with a Microsoft token +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] +pub struct XboxLiveAuthenticationResponseError { + /// Always zero + identity: String, + + /// Error id + /// 2148916238 means <18 and needs to be added to microsoft family + /// 2148916233 means xbox account needs to be created + x_err: i64, + + /// Message about error + message: String, + + /// Where to go to fix the error as a user + redirect: String, +} + /// The flow for authenticating with a Microsoft access token and getting a /// Minecraft access token. pub struct MinecraftAuthorizationFlow { @@ -188,9 +215,23 @@ impl MinecraftAuthorizationFlow { })) .send() .await?; - response.error_for_status_ref()?; - let xbox_security_token_resp: XboxLiveAuthenticationResponse = response.json().await?; - Ok(xbox_security_token_resp) + if response.status() == StatusCode::UNAUTHORIZED { + let xbox_security_token_err_resp_res = response.json().await; + if xbox_security_token_err_resp_res.is_err() { + return Err(MinecraftAuthorizationError::MissingClaims); + } + let xbox_security_token_err_resp: XboxLiveAuthenticationResponseError = + xbox_security_token_err_resp_res.expect("This should succeed always"); + match xbox_security_token_err_resp.x_err { + 2148916238 => Err(MinecraftAuthorizationError::AddToFamily), + 2148916233 => Err(MinecraftAuthorizationError::NoXbox), + _ => Err(MinecraftAuthorizationError::MissingClaims), + } + } else { + response.error_for_status_ref()?; + let xbox_security_token_resp: XboxLiveAuthenticationResponse = response.json().await?; + Ok(xbox_security_token_resp) + } } async fn xbox_token(