Skip to content

Commit

Permalink
修正了因密码结构使用不当导致微软账户登录失败的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
Steve-xmh committed Nov 6, 2023
1 parent 906828e commit 064068e
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 19 deletions.
16 changes: 12 additions & 4 deletions scl-core/src/auth/microsoft/leagcy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,16 +173,18 @@ pub async fn get_mojang_access_token(uhs: &str, xsts_token: &str) -> DynResult<P
if !uhs.is_empty() && !xsts_token.is_empty() {
// tracing::trace!("Getting mojang access token");
let minecraft_xbox_body = format!("{{\"identityToken\":\"XBL3.0 x={uhs};{xsts_token}\"}}");
let minecraft_xbox_resp: MinecraftXBoxLoginResponse =
let minecraft_xbox_resp =
crate::http::post("https://api.minecraftservices.com/authentication/login_with_xbox")
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.body(minecraft_xbox_body.as_bytes())
.await
.map_err(|e| anyhow::anyhow!(e))?
.body_json()
.body_string()
.await
.map_err(|e| anyhow::anyhow!(e))?;
let minecraft_xbox_resp: MinecraftXBoxLoginResponse =
serde_json::from_str(&minecraft_xbox_resp)?;
// tracing::trace!("Getting minecraft access token");
let access_token = minecraft_xbox_resp.access_token;
Ok(access_token)
Expand Down Expand Up @@ -231,7 +233,10 @@ pub async fn start_auth(_ctx: Option<impl Reporter>, url: &str) -> DynResult<Aut
} else {
let mcstore_resp: MinecraftStoreResponse =
crate::http::get("https://api.minecraftservices.com/entitlements/mcstore")
.header("Authorization", &format!("Bearer {}", &access_token))
.header(
"Authorization",
&format!("Bearer {}", access_token.as_string()),
)
.await
.map_err(|e| anyhow::anyhow!(e))?
.body_json()
Expand All @@ -244,7 +249,10 @@ pub async fn start_auth(_ctx: Option<impl Reporter>, url: &str) -> DynResult<Aut
}
let profile_resp: MinecraftXBoxProfileResponse =
crate::http::get("https://api.minecraftservices.com/minecraft/profile")
.header("Authorization", &format!("Bearer {}", &access_token))
.header(
"Authorization",
&format!("Bearer {}", access_token.as_string()),
)
.await
.map_err(|e| anyhow::anyhow!(e))?
.body_json()
Expand Down
39 changes: 24 additions & 15 deletions scl-core/src/auth/microsoft/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use std::fmt::Display;

use anyhow::Context;
use serde::Deserialize;

use super::structs::AuthMethod;
Expand Down Expand Up @@ -75,7 +76,7 @@ impl<T: Display> MicrosoftOAuth<T> {
}

async fn auth_xbox_live(&self, access_token: &str) -> DynResult<(String, String)> {
tracing::trace!("正在验证 Xbox Live 账户");
tracing::debug!("正在验证 Xbox Live 账户");
let xbox_auth_body = format!(
"{\
{\
Expand Down Expand Up @@ -116,7 +117,7 @@ impl<T: Display> MicrosoftOAuth<T> {
}\
}"
);
tracing::trace!("正在获取 XSTS");
tracing::debug!("正在获取 XSTS");
let xsts_resp: XBoxAuthResponse =
crate::http::post("https://xsts.auth.xboxlive.com/xsts/authorize")
.header("Content-Type", "application/json")
Expand All @@ -140,49 +141,57 @@ impl<T: Display> MicrosoftOAuth<T> {
) -> DynResult<AuthMethod> {
let (uhs, xsts_token) = self.auth_xbox_live(access_token).await?;

tracing::trace!("正在获取 XUID");
tracing::debug!("正在获取 XUID");
let xuid = leagcy::get_xuid(&uhs, &xsts_token).await?;

tracing::trace!("正在获取 Mojang 访问令牌");
tracing::debug!("正在获取 Mojang 访问令牌");
let access_token = leagcy::get_mojang_access_token(&uhs, &xsts_token).await?;

if access_token.is_empty() {
anyhow::bail!("获取令牌失败")
} else {
tracing::trace!("正在检查是否拥有 Minecraft");
let mcstore_resp: MinecraftStoreResponse =
tracing::debug!("正在检查是否拥有 Minecraft");
let mcstore_resp =
crate::http::get("https://api.minecraftservices.com/entitlements/mcstore")
.header("Authorization", &format!("Bearer {}", &access_token))
.header(
"Authorization",
&format!("Bearer {}", &access_token.as_string()),
)
.await
.map_err(|e| anyhow::anyhow!(e))?
.body_json()
.body_string()
.await
.map_err(|e| anyhow::anyhow!(e))?;
let mcstore_resp: MinecraftStoreResponse = serde_json::from_str(&mcstore_resp)?;
if mcstore_resp.items.is_empty() {
anyhow::bail!(
"没有在已购项目中找到 Minecraft!请检查你的账户是否已购买 Minecraft!"
);
}
tracing::trace!("正在获取 Minecraft 账户信息");
tracing::debug!("正在获取 Minecraft 账户信息");
let profile_resp: MinecraftXBoxProfileResponse =
crate::http::get("https://api.minecraftservices.com/minecraft/profile")
.header("Authorization", &format!("Bearer {}", &access_token))
.header(
"Authorization",
&format!("Bearer {}", &access_token.as_string()),
)
.await
.map_err(|e| anyhow::anyhow!(e))?
.body_json()
.await
.map_err(|e| anyhow::anyhow!(e))?;
if profile_resp.error.is_empty() {
if let Some(skin) = profile_resp.skins.iter().find(|a| a.state == "ACTIVE") {
tracing::trace!("正在解析皮肤");
tracing::debug!("正在解析皮肤: {}", skin.url);
let skin_data = crate::http::get(&skin.url)
.await
.map_err(|e| anyhow::anyhow!(e))?
.body_bytes()
.await
.map_err(|e| anyhow::anyhow!(e))?;
let (head_skin, hat_skin) = crate::auth::parse_head_skin(skin_data)?;
tracing::trace!("微软账户验证成功!");
let (head_skin, hat_skin) =
crate::auth::parse_head_skin(skin_data).context("解析皮肤数据失败")?;
tracing::debug!("微软账户验证成功!");
Ok(AuthMethod::Microsoft {
access_token,
refresh_token: refresh_token.to_string().into(),
Expand Down Expand Up @@ -211,14 +220,14 @@ impl<T: Display> MicrosoftOAuth<T> {
..
} = method
{
tracing::trace!("正在刷新令牌");
tracing::debug!("正在刷新令牌");
let new_token = self.refresh_token(refresh_token.as_str()).await?;

*refresh_token = new_token.refresh_token.into();

let (uhs, xsts_token) = self.auth_xbox_live(&new_token.access_token).await?;

tracing::trace!("正在获取 Mojang 访问令牌");
tracing::debug!("正在获取 Mojang 访问令牌");
let new_access_token = leagcy::get_mojang_access_token(&uhs, &xsts_token).await?;

anyhow::ensure!(
Expand Down
2 changes: 2 additions & 0 deletions scl-core/src/password.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use std::{
use serde::{de::Visitor, Deserialize, Deserializer, Serialize};

/// 一个密码类,String 的壳子,用来在调试输出时挡住真实密码,防止泄露
///
/// 任何格式化输出都会返回 `***Password***`,所以如果需要取用密码,请使用 [`Password::take_string`] [`Password::to_owned_string`] [`Password::as_string`]
#[derive(Clone, PartialEq, Eq, Default)]
pub struct Password(String);

Expand Down

0 comments on commit 064068e

Please sign in to comment.