接入google play token 校验
This commit is contained in:
parent
a99589283a
commit
c51f80b2f3
@ -45,6 +45,10 @@ pub struct GoogleJwtProfile {
|
|||||||
pub given_name: String,
|
pub given_name: String,
|
||||||
pub family_name: String,
|
pub family_name: String,
|
||||||
pub locale: String,
|
pub locale: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub google_play_games_id: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub google_play_games_profile: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GoogleJwtProfile {
|
impl GoogleJwtProfile {
|
||||||
@ -159,4 +163,76 @@ impl GoogleSocial {
|
|||||||
|
|
||||||
Ok(google_jwt_profile)
|
Ok(google_jwt_profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 验证 Google Play Games 的身份信息
|
||||||
|
/// 参考: https://developers.google.com/games/services/android/signin
|
||||||
|
pub async fn verify_play_games_token(&self, play_games_token: &str) -> SocialResult<GoogleJwtProfile> {
|
||||||
|
// Google Play Games 的验证端点
|
||||||
|
const GOOGLE_PLAY_GAMES_TOKEN_INFO_URL: &str =
|
||||||
|
"https://oauth2.googleapis.com/tokeninfo";
|
||||||
|
|
||||||
|
let client = Client::new();
|
||||||
|
let response = client
|
||||||
|
.get(GOOGLE_PLAY_GAMES_TOKEN_INFO_URL)
|
||||||
|
.query(&[("access_token", play_games_token)])
|
||||||
|
.send()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if !response.status().is_success() {
|
||||||
|
return Err(Box::new(ResErr::social("验证 Google Play Games Token 失败")));
|
||||||
|
}
|
||||||
|
|
||||||
|
let token_info: Value = response.json().await?;
|
||||||
|
|
||||||
|
// 验证 token 信息
|
||||||
|
if let Some(error) = token_info.get("error") {
|
||||||
|
return Err(Box::new(ResErr::social(format!(
|
||||||
|
"Google Play Games Token 无效: {}",
|
||||||
|
error
|
||||||
|
))));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证 audience 是否匹配你的应用
|
||||||
|
if let Some(aud) = token_info.get("aud") {
|
||||||
|
// TODO: 验证 aud 是否匹配你的 Google Play Games 应用 ID
|
||||||
|
tracing::debug!("Google Play Games aud: {}", aud);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建用户资料
|
||||||
|
let mut profile = GoogleJwtProfile::default();
|
||||||
|
if let Some(sub) = token_info.get("sub").and_then(|v| v.as_str()) {
|
||||||
|
profile.sub = sub.to_string();
|
||||||
|
}
|
||||||
|
if let Some(email) = token_info.get("email").and_then(|v| v.as_str()) {
|
||||||
|
profile.email = email.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 Google Play Games 特定的信息
|
||||||
|
let play_games_info = self.fetch_play_games_profile(play_games_token).await?;
|
||||||
|
profile.google_play_games_id = play_games_info.get("playerId")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.map(String::from);
|
||||||
|
|
||||||
|
Ok(profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取 Google Play Games 用户资料
|
||||||
|
async fn fetch_play_games_profile(&self, access_token: &str) -> SocialResult<Value> {
|
||||||
|
const PLAY_GAMES_PROFILE_URL: &str =
|
||||||
|
"https://games.googleapis.com/games/v1/players/me";
|
||||||
|
|
||||||
|
let client = Client::new();
|
||||||
|
let response = client
|
||||||
|
.get(PLAY_GAMES_PROFILE_URL)
|
||||||
|
.header("Authorization", format!("Bearer {}", access_token))
|
||||||
|
.send()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if !response.status().is_success() {
|
||||||
|
return Err(Box::new(ResErr::social("获取 Google Play Games 用户资料失败")));
|
||||||
|
}
|
||||||
|
|
||||||
|
let profile: Value = response.json().await?;
|
||||||
|
Ok(profile)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user