添加google账号 id token校验
This commit is contained in:
parent
94aaedf986
commit
b6032bc286
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1065,6 +1065,7 @@ dependencies = [
|
|||||||
"jsonwebtoken",
|
"jsonwebtoken",
|
||||||
"moka",
|
"moka",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
@ -1639,6 +1640,7 @@ dependencies = [
|
|||||||
"base64 0.22.0",
|
"base64 0.22.0",
|
||||||
"bytes",
|
"bytes",
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"h2",
|
"h2",
|
||||||
|
@ -24,4 +24,5 @@ http-body-util = { workspace = true }
|
|||||||
moka = { workspace = true, features = ["future"] }
|
moka = { workspace = true, features = ["future"] }
|
||||||
tokio = { workspace = true, features = ["rt-multi-thread", "macros" ] }
|
tokio = { workspace = true, features = ["rt-multi-thread", "macros" ] }
|
||||||
futures-util = { workspace = true }
|
futures-util = { workspace = true }
|
||||||
jsonwebtoken = { workspace = true }
|
jsonwebtoken = { workspace = true }
|
||||||
|
reqwest = { workspace = true, features = ["blocking", "json"] }
|
@ -2,4 +2,3 @@ pub mod config;
|
|||||||
pub mod logger;
|
pub mod logger;
|
||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod local_cache;
|
pub mod local_cache;
|
||||||
pub mod auth_cache;
|
|
||||||
|
@ -3,4 +3,6 @@ extern crate self as library;
|
|||||||
pub mod core;
|
pub mod core;
|
||||||
pub mod resp;
|
pub mod resp;
|
||||||
pub mod middleware;
|
pub mod middleware;
|
||||||
pub mod token;
|
pub mod token;
|
||||||
|
pub mod cache;
|
||||||
|
pub mod social;
|
64
library/src/social/google.rs
Normal file
64
library/src/social/google.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use jsonwebtoken::{decode, errors::{Error, ErrorKind}, Algorithm, DecodingKey, TokenData, Validation};
|
||||||
|
use reqwest::Client;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
|
type SocialResult<T> = Result<T, Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
|
// 假设GOOGLE_PUBLIC_CERT_URL是Google提供的公钥URL
|
||||||
|
const GOOGLE_PUBLIC_CERT_URL: &str = "https://www.googleapis.com/oauth2/v3/certs";
|
||||||
|
|
||||||
|
// 异步获取并解析Google公钥
|
||||||
|
async fn fetch_and_parse_google_public_keys() -> SocialResult<HashMap<String, String>> {
|
||||||
|
let response = Client::new().get(GOOGLE_PUBLIC_CERT_URL).send().await?;
|
||||||
|
let google_keys: Value = response.json().await?;
|
||||||
|
|
||||||
|
let mut key_map = HashMap::new();
|
||||||
|
if let Value::Object(keys_obj) = google_keys {
|
||||||
|
for (kid, key_val) in keys_obj {
|
||||||
|
if let Value::String(key) = key_val {
|
||||||
|
key_map.insert(kid, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(key_map)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证ID Token并考虑kid匹配
|
||||||
|
async fn verify_id_token(id_token: &str) -> SocialResult<Value> {
|
||||||
|
// 获取并解析公钥
|
||||||
|
let public_keys = fetch_and_parse_google_public_keys().await?;
|
||||||
|
|
||||||
|
// 解码Token头部以获取kid
|
||||||
|
let token_header = jsonwebtoken::decode_header(id_token).unwrap();
|
||||||
|
let kid = token_header.kid;
|
||||||
|
|
||||||
|
// 检查是否找到了有效的kid
|
||||||
|
if kid.is_none() {
|
||||||
|
return Err(Box::new(Error::from(ErrorKind::InvalidToken)));
|
||||||
|
}
|
||||||
|
let kid = kid.unwrap();
|
||||||
|
|
||||||
|
// 根据kid找到正确的公钥
|
||||||
|
let key = public_keys.get(&kid).ok_or_else(|| Box::new(Error::from(ErrorKind::InvalidToken)))?;
|
||||||
|
|
||||||
|
// 验证Token
|
||||||
|
let mut validation: Validation = Validation::new(Algorithm::RS256);
|
||||||
|
validation.set_issuer(&["https://accounts.google.com"]);// 设置预期的发行者
|
||||||
|
|
||||||
|
let decoded = decode::<Value>(id_token, &DecodingKey::from_rsa_pem(key.as_bytes())?, &validation)?;
|
||||||
|
|
||||||
|
let claims = decoded.claims;
|
||||||
|
// 进一步校验iss字段
|
||||||
|
if let Some(issuer) = claims.get("iss") {
|
||||||
|
if issuer.as_str().unwrap() != "https://accounts.google.com" {
|
||||||
|
return Err(Box::new(Error::from(ErrorKind::InvalidToken)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(Box::new(Error::from(ErrorKind::InvalidToken)));
|
||||||
|
}
|
||||||
|
Ok(claims)
|
||||||
|
|
||||||
|
}
|
2
library/src/social/mod.rs
Normal file
2
library/src/social/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
pub mod google;
|
Loading…
Reference in New Issue
Block a user