use super::*;
use crate::error::{Result, LateJavaCoreError};
use reqwest::Client;
use serde_json::json;
use uuid::Uuid;
pub struct AZauthAuth {
base_url: String,
client: Client,
}
impl AZauthAuth {
pub fn new(base_url: String) -> Self {
Self {
base_url,
client: Client::new(),
}
}
pub async fn authenticate(&self, username: &str, password: &str) -> Result<AuthResponse> {
let response = self.client
.post(&format!("{}/authserver/authenticate", self.base_url))
.json(&json!({
"agent": {
"name": "Minecraft",
"version": 1
},
"username": username,
"password": password,
"clientToken": Uuid::new_v4().to_string()
}))
.send()
.await?;
let auth_response: serde_json::Value = response.json().await?;
if let Some(error) = auth_response.get("error") {
return Err(LateJavaCoreError::Auth(format!("AZauth error: {}", error)));
}
let selected_profile = auth_response["selectedProfile"]
.as_object()
.ok_or_else(|| LateJavaCoreError::Auth("No selected profile".to_string()))?;
Ok(AuthResponse {
access_token: auth_response["accessToken"]
.as_str()
.unwrap_or("")
.to_string(),
client_token: auth_response["clientToken"]
.as_str()
.unwrap_or("")
.to_string(),
uuid: selected_profile["id"]
.as_str()
.unwrap_or("")
.to_string(),
name: selected_profile["name"]
.as_str()
.unwrap_or("")
.to_string(),
refresh_token: None,
user_properties: auth_response["user"]
.get("properties")
.map(|p| p.to_string())
.unwrap_or_else(|| "{}".to_string()),
meta: AuthMeta {
auth_type: "AZauth".to_string(),
access_token_expires_in: chrono::Utc::now().timestamp() as u64 + 86400, demo: false,
},
xbox_account: None,
profile: None,
})
}
pub async fn refresh(&self, auth: AuthResponse) -> Result<AuthResponse> {
let response = self.client
.post(&format!("{}/authserver/refresh", self.base_url))
.json(&json!({
"accessToken": auth.access_token,
"clientToken": auth.client_token
}))
.send()
.await?;
let auth_response: serde_json::Value = response.json().await?;
if let Some(error) = auth_response.get("error") {
return Err(LateJavaCoreError::Auth(format!("AZauth refresh error: {}", error)));
}
let selected_profile = auth_response["selectedProfile"]
.as_object()
.ok_or_else(|| LateJavaCoreError::Auth("No selected profile".to_string()))?;
Ok(AuthResponse {
access_token: auth_response["accessToken"]
.as_str()
.unwrap_or("")
.to_string(),
client_token: auth_response["clientToken"]
.as_str()
.unwrap_or("")
.to_string(),
uuid: selected_profile["id"]
.as_str()
.unwrap_or("")
.to_string(),
name: selected_profile["name"]
.as_str()
.unwrap_or("")
.to_string(),
refresh_token: None,
user_properties: auth_response["user"]
.get("properties")
.map(|p| p.to_string())
.unwrap_or_else(|| "{}".to_string()),
meta: AuthMeta {
auth_type: "AZauth".to_string(),
access_token_expires_in: chrono::Utc::now().timestamp() as u64 + 86400,
demo: false,
},
xbox_account: None,
profile: None,
})
}
pub async fn validate(&self, access_token: &str, client_token: &str) -> Result<bool> {
let response = self.client
.post(&format!("{}/authserver/validate", self.base_url))
.json(&json!({
"accessToken": access_token,
"clientToken": client_token
}))
.send()
.await?;
Ok(response.status().is_success())
}
pub async fn invalidate(&self, access_token: &str, client_token: &str) -> Result<()> {
self.client
.post(&format!("{}/authserver/invalidate", self.base_url))
.json(&json!({
"accessToken": access_token,
"clientToken": client_token
}))
.send()
.await?;
Ok(())
}
}