添加firebase id token 校验
This commit is contained in:
parent
ec6b061ed7
commit
4db49d4dc6
27
Cargo.lock
generated
27
Cargo.lock
generated
@ -171,7 +171,11 @@ dependencies = [
|
|||||||
name = "auth"
|
name = "auth"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"error-stack",
|
||||||
|
"futures-executor",
|
||||||
|
"reqwest",
|
||||||
"rs-firebase-admin-sdk",
|
"rs-firebase-admin-sdk",
|
||||||
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2022,6 +2026,7 @@ dependencies = [
|
|||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"h2 0.4.2",
|
||||||
"http 1.1.0",
|
"http 1.1.0",
|
||||||
"http-body 1.0.0",
|
"http-body 1.0.0",
|
||||||
"http-body-util",
|
"http-body-util",
|
||||||
@ -2041,6 +2046,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"sync_wrapper",
|
"sync_wrapper",
|
||||||
|
"system-configuration",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-native-tls",
|
"tokio-native-tls",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
@ -2910,6 +2916,27 @@ version = "0.1.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "system-configuration"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"core-foundation",
|
||||||
|
"system-configuration-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "system-configuration-sys"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tagptr"
|
name = "tagptr"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -7,3 +7,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rs-firebase-admin-sdk = "2.0.0"
|
rs-firebase-admin-sdk = "2.0.0"
|
||||||
|
reqwest = "0.12.4"
|
||||||
|
futures-executor = "0.3.30"
|
||||||
|
error-stack = "0.4.1"
|
||||||
|
tracing = "0.1.40"
|
||||||
|
@ -1,8 +1,44 @@
|
|||||||
|
use std::sync::OnceLock;
|
||||||
|
use error_stack::Report;
|
||||||
|
use futures_executor::block_on;
|
||||||
use rs_firebase_admin_sdk::{
|
use rs_firebase_admin_sdk::{
|
||||||
auth::{FirebaseAuthService, UserIdentifiers},
|
auth::{FirebaseAuthService, UserIdentifiers},
|
||||||
client::ApiHttpClient,
|
client::ApiHttpClient,
|
||||||
App, AuthenticationManager,
|
App, AuthenticationManager,
|
||||||
};
|
};
|
||||||
|
use rs_firebase_admin_sdk::auth::token::{LiveTokenVerifier, TokenVerifier};
|
||||||
|
use rs_firebase_admin_sdk::auth::token::cache::{HttpCache, PubKeys};
|
||||||
|
use rs_firebase_admin_sdk::auth::token::error::TokenVerificationError;
|
||||||
|
use rs_firebase_admin_sdk::auth::token::jwt::JWToken;
|
||||||
|
|
||||||
|
static LIVE_APP: OnceLock<App<AuthenticationManager>> = OnceLock::new();
|
||||||
|
|
||||||
|
static ID_TOKEN_VERIFIER: OnceLock<LiveTokenVerifier<HttpCache<reqwest::Client, PubKeys>>> = OnceLock::new();
|
||||||
|
|
||||||
|
fn get_app() -> &'static App<AuthenticationManager> {
|
||||||
|
LIVE_APP.get_or_init(|| block_on(async {
|
||||||
|
let gcp_service_account = AuthenticationManager::new().await.expect("Error while creating authentication manager");
|
||||||
|
App::live(gcp_service_account.into()).await.expect("Error while creating live app")
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_id_token_verifier() -> &'static LiveTokenVerifier<HttpCache<reqwest::Client, PubKeys>> {
|
||||||
|
ID_TOKEN_VERIFIER.get_or_init(|| block_on(async {
|
||||||
|
get_app().id_token_verifier().await.expect("Error while creating id token verifier")
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn verify_user_id_token(id_token: &str) -> Result<JWToken, String> {
|
||||||
|
match get_id_token_verifier().verify_token(id_token).await {
|
||||||
|
Ok(jwtToken) => {
|
||||||
|
Ok(jwtToken)
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
tracing::error!("Error while verifying token: {:?}", error);
|
||||||
|
Err(error.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn test() {
|
async fn test() {
|
||||||
// Load your GCP SA from env, see https://crates.io/crates/gcp_auth for more details
|
// Load your GCP SA from env, see https://crates.io/crates/gcp_auth for more details
|
||||||
@ -10,6 +46,8 @@ async fn test() {
|
|||||||
// Create live (not emulated) context for Firebase app
|
// Create live (not emulated) context for Firebase app
|
||||||
let live_app = App::live(gcp_service_account.into()).await.unwrap();
|
let live_app = App::live(gcp_service_account.into()).await.unwrap();
|
||||||
|
|
||||||
|
let id_token_verifier = live_app.id_token_verifier().await.expect("Error while creating id token verifier");
|
||||||
|
let verify_result = id_token_verifier.verify_token("").await.expect("Error while verifying token");
|
||||||
// Create Firebase authentication admin client
|
// Create Firebase authentication admin client
|
||||||
let auth_admin = live_app.auth();
|
let auth_admin = live_app.auth();
|
||||||
|
|
||||||
|
@ -5,12 +5,14 @@ use validator::Validate;
|
|||||||
pub struct PlayerInfoRegister {
|
pub struct PlayerInfoRegister {
|
||||||
#[validate(required(message = "用户名称不能为空"), length(min = 1, message = "用户名称不能为空"))]
|
#[validate(required(message = "用户名称不能为空"), length(min = 1, message = "用户名称不能为空"))]
|
||||||
pub username: Option<String>,
|
pub username: Option<String>,
|
||||||
#[validate(required, length(min = 1, message = "电子邮箱不能为空"))]
|
#[validate(required(message = "电子邮箱不能为空"), length(min = 1, message = "电子邮箱不能为空"))]
|
||||||
pub email: Option<String>,
|
pub email: Option<String>,
|
||||||
#[validate(required, length(min = 1, message = "平台ID不能为空"))]
|
#[validate(required(message = "平台ID不能为空"), length(min = 1, message = "平台ID不能为空"))]
|
||||||
pub platform_id: Option<String>,
|
pub platform_id: Option<String>,
|
||||||
#[validate(required, length(min = 1, message = "用户类型不能为空"))]
|
#[validate(required(message = "用户类型不能为空"), length(min = 1, message = "用户类型不能为空"))]
|
||||||
pub user_type: Option<String>,
|
pub user_type: Option<String>,
|
||||||
#[validate(required, length(min = 1, message = "用户所属区域不能为空"))]
|
#[validate(required(message = "用户所属区域不能为空"), length(min = 1, message = "用户所属区域不能为空"))]
|
||||||
pub country_code: Option<String>,
|
pub country_code: Option<String>,
|
||||||
|
#[validate(required(message = "用户ID Token不能为空"), length(min = 1, message = "用户ID Token不能为空"))]
|
||||||
|
pub idToken: Option<String>
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ use library::db;
|
|||||||
use library::resp::response::ResErr::{ErrPerm, ErrSystem};
|
use library::resp::response::ResErr::{ErrPerm, ErrSystem};
|
||||||
use library::resp::response::{ResOK, ResResult};
|
use library::resp::response::{ResOK, ResResult};
|
||||||
use sea_orm::{ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, Set};
|
use sea_orm::{ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, Set};
|
||||||
|
use auth::firebase_admin;
|
||||||
|
|
||||||
pub async fn register(req: PlayerInfoRegister) -> ResResult<ResOK<()>> {
|
pub async fn register(req: PlayerInfoRegister) -> ResResult<ResOK<()>> {
|
||||||
match PlayerInfo::find()
|
match PlayerInfo::find()
|
||||||
@ -23,6 +24,14 @@ pub async fn register(req: PlayerInfoRegister) -> ResResult<ResOK<()>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let verified_token = match firebase_admin::verify_user_id_token(req.idToken.unwrap().as_str()).await {
|
||||||
|
Ok(token) => token,
|
||||||
|
Err(err) => {
|
||||||
|
tracing::error!(error = ?err, "err verify user id token");
|
||||||
|
return Err(ErrSystem(None));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let now = chrono::Local::now().naive_local();
|
let now = chrono::Local::now().naive_local();
|
||||||
|
|
||||||
let model = player_info::ActiveModel {
|
let model = player_info::ActiveModel {
|
||||||
|
Loading…
Reference in New Issue
Block a user