diff options
| author | 2025-02-01 23:06:37 -0600 | |
|---|---|---|
| committer | 2025-02-01 23:06:37 -0600 | |
| commit | c19a1077e85334a3e5ba885a60b03d76409a2b2e (patch) | |
| tree | 5e726e8180770ac9c2f6c415a0437d6d2c29c226 /src/auth/msa.rs | |
| parent | random changes (diff) | |
restructure project
Diffstat (limited to 'src/auth/msa.rs')
| -rw-r--r-- | src/auth/msa.rs | 170 |
1 files changed, 0 insertions, 170 deletions
diff --git a/src/auth/msa.rs b/src/auth/msa.rs deleted file mode 100644 index add345c..0000000 --- a/src/auth/msa.rs +++ /dev/null @@ -1,170 +0,0 @@ -use std::borrow::Cow; -use std::collections::HashMap; -use chrono::{DateTime, Utc}; -use log::debug; -use oauth2::AccessToken; -use reqwest::{Method}; -use serde::{Deserialize, Serialize}; -use uuid::Uuid; -use crate::auth::AuthError; -use crate::auth::types::Token; - -const XBOX_LIVE_AUTH: &str = "https://user.auth.xboxlive.com/user/authenticate"; -const XBOX_LIVE_XSTS: &str = "https://xsts.auth.xboxlive.com/xsts/authorize"; - -#[derive(Debug, Serialize)] -#[serde(rename_all = "PascalCase")] -struct XboxLiveAuthRequestProperties<'a> { - auth_method: &'a str, - site_name: &'a str, - rps_ticket: &'a str -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "PascalCase")] -struct XboxLiveAuthRequest<'a> { - properties: XboxLiveAuthRequestProperties<'a>, - relying_party: &'a str, - token_type: &'a str -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "PascalCase")] -struct XboxLiveAuthResponse { - token: String, - not_after: DateTime<Utc> -} - -pub async fn xbox_live_login(client: &reqwest::Client, access_token: &AccessToken, azure: bool) -> Result<Token, AuthError> { - debug!("MSA performing xbox live login ({azure})"); - - let ticket = match azure { - true => Cow::Owned(format!("d={}", access_token.secret())), - _ => Cow::Borrowed(access_token.secret().as_str()) - }; - - let request = XboxLiveAuthRequest { - properties: XboxLiveAuthRequestProperties { - auth_method: "RPS", - site_name: "user.auth.xboxlive.com", - rps_ticket: ticket.as_ref() - }, - relying_party: "http://auth.xboxlive.com", - token_type: "JWT" - }; - - let res: XboxLiveAuthResponse = super::build_json_request(client, XBOX_LIVE_AUTH, Method::POST).json(&request).send().await - .and_then(|r| r.error_for_status()) - .map_err(|e| AuthError::Request { what: "xbox live auth", error: e })? - .json().await.map_err(|e| AuthError::Request { what: "xbox live auth (decode)", error: e })?; - - Ok(Token { - value: res.token, - expire: Some(res.not_after) - }) -} - -#[derive(Serialize, Debug)] -#[serde(rename_all = "PascalCase")] -struct XSTSAuthRequest<'a> { - properties: XSTSAuthRequestProperties<'a>, - relying_party: &'a str, - token_type: &'a str -} - -#[derive(Serialize, Debug)] -#[serde(rename_all = "PascalCase")] -struct XSTSAuthRequestProperties<'a> { - sandbox_id: &'a str, - user_tokens: &'a[&'a str] -} - -#[derive(Deserialize, Debug)] -#[serde(rename_all = "PascalCase")] -pub(super) struct XSTSAuthSuccessResponse { - token: String, - #[serde(default)] - display_claims: XSTSAuthResponseDisplayClaims -} - -#[derive(Deserialize, Debug)] -#[serde(rename_all = "PascalCase")] -pub(super) struct XSTSAuthErrorResponse { - x_err: u64, - message: Option<String> -} - -#[derive(Deserialize, Debug)] -#[serde(rename_all = "PascalCase", untagged)] -pub(super) enum XSTSAuthResponse { - Success(XSTSAuthSuccessResponse), - Error(XSTSAuthErrorResponse) -} - -#[derive(Deserialize, Debug, Default)] -pub(super) struct XSTSAuthResponseDisplayClaims { - xui: Vec<HashMap<String, String>> -} - -impl XSTSAuthSuccessResponse { - pub(super) fn into_token(self) -> String { - self.token - } - - fn get_display_claim(&self, name: &str) -> Option<&str> { - self.display_claims.xui.iter().find(|m| m.contains_key(name)).and_then(|f| f.get(name).map(|s| s.as_str())) - } - - pub(super) fn get_user_hash(&self) -> Option<&str> { - self.get_display_claim("uhs") - } - - pub(super) fn get_xuid(&self) -> Option<&str> { - self.get_display_claim("xid") - } - - pub(super) fn get_gamertag(&self) -> Option<&str> { - self.get_display_claim("gtg") - } -} - -#[allow(clippy::from_over_into)] -impl Into<AuthError> for XSTSAuthErrorResponse { - fn into(self) -> AuthError { - AuthError::AuthXError { - // some well-known error values - what: match self.x_err { - 2148916238u64 => "Microsoft account held by a minor outside of a family.", - 2148916233u64 => "Account is not on Xbox.", - _ => "Unknown error." - }, - x_error: self.x_err, - message: self.message - } - } -} - -pub(super) const XSTS_RP_MINECRAFT_SERVICES: &str = "rp://api.minecraftservices.com/"; -pub(super) const XSTS_RP_XBOX_LIVE: &str = "http://xboxlive.com"; - -pub async fn xsts_request(client: &reqwest::Client, xbl_token: &str, relying_party: &str) -> Result<XSTSAuthResponse, AuthError> { - debug!("Performing XSTS auth {relying_party}"); - - let token_array = [xbl_token]; - let req = XSTSAuthRequest { - properties: XSTSAuthRequestProperties { - sandbox_id: "RETAIL", - user_tokens: token_array.as_slice() - }, - relying_party, - token_type: "JWT" - }; - - let res: XSTSAuthResponse = super::build_json_request(client, XBOX_LIVE_XSTS, Method::POST).json(&req).send().await - .and_then(|r| r.error_for_status()) - .map_err(|e| AuthError::Request { what: "xsts", error: e })? - .json().await - .map_err(|e| AuthError::Request { what: "xsts (decode)", error: e })?; - - Ok(res) -} |
