use aurabase::create_client;
use aurabase::services::auth::{OAUTH_FORWARDABLE_QUERY_PARAMS, OAUTH_SDK_OWNED_QUERY_PARAMS};
use aurabase::types::OAuthSignInOptions;
use std::collections::HashMap;
const BASE: &str = "https://mon-projet.aurabase.cloud";
fn options(query_params: &[(&str, &str)]) -> OAuthSignInOptions {
OAuthSignInOptions {
redirect_to: None,
scopes: None,
query_params: Some(
query_params
.iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect::<HashMap<_, _>>(),
),
}
}
#[allow(clippy::result_large_err)]
fn url(query_params: &[(&str, &str)]) -> Result<String, aurabase::error::AuraError> {
create_client(BASE, "aura_anon_test", None)
.auth()
.sign_in_with_oauth("google", Some(options(query_params)))
}
#[test]
fn transmet_les_parametres_dexperience_legitimes() {
let u = url(&[
("prompt", "consent"),
("login_hint", "a@b.c"),
("access_type", "offline"),
("hd", "ex.com"),
])
.expect("paramètres d'expérience légitimes");
for attendu in [
"prompt=consent",
"login_hint=a%40b.c",
"access_type=offline",
"hd=ex.com",
] {
assert!(u.contains(attendu), "{attendu} absent de : {u}");
}
}
#[test]
fn refuse_un_parametre_du_protocole_sans_rien_ignorer() {
for cle in ["state", "client_id", "response_type", "scope", "nonce"] {
let err = url(&[(cle, "x")])
.expect_err("un paramètre du protocole est calculé par le serveur, jamais reçu");
assert_eq!(err.code, "invalid_oauth_query_param", "{cle}");
assert!(err.message.contains(cle), "{cle} : {}", err.message);
}
}
#[test]
fn refuse_une_cle_qui_ecraserait_un_parametre_du_sdk() {
for cle in OAUTH_SDK_OWNED_QUERY_PARAMS {
let err = url(&[(cle, "https://attaquant.test/vol")])
.expect_err("un paramètre construit par le SDK ne peut pas venir de l'appelant");
assert_eq!(err.code, "invalid_oauth_query_param", "{cle}");
assert!(err.message.contains(cle), "{cle} : {}", err.message);
}
}
#[test]
fn refuse_une_cle_inconnue_en_nommant_lensemble_autorise() {
for cle in ["utm_source", "Prompt", "State"] {
let err = url(&[(cle, "x")]).expect_err("clé inconnue");
assert!(err.message.contains(cle), "{cle} : {}", err.message);
assert!(
err.message.contains("prompt"),
"le refus doit nommer l'ensemble autorisé : {}",
err.message
);
}
}
#[test]
fn le_redirect_to_de_lappelant_survit_a_un_query_params_legitime() {
let u = create_client(BASE, "aura_anon_test", None)
.auth()
.sign_in_with_oauth(
"google",
Some(OAuthSignInOptions {
redirect_to: Some("https://app.test/cb".into()),
scopes: None,
query_params: Some(HashMap::from([(
"prompt".to_string(),
"consent".to_string(),
)])),
}),
)
.expect("options légitimes");
assert!(u.contains("redirect_to=https%3A%2F%2Fapp.test%2Fcb"), "{u}");
assert_eq!(
u.matches("redirect_to=").count(),
1,
"une clé répétée est refusée en 400 par aura-auth : {u}"
);
}
#[test]
fn lordre_des_parametres_est_stable() {
let cas = &[("prompt", "consent"), ("login_hint", "a@b.c"), ("hd", "x")];
let premier = url(cas).expect("légitime");
for _ in 0..20 {
assert_eq!(url(cas).expect("légitime"), premier);
}
}
#[test]
fn le_chemin_ne_porte_ni_project_id_ni_parametre_de_projet() {
let u = create_client(BASE, "aura_anon_test", None)
.auth()
.sign_in_with_oauth("google", None)
.expect("aucun query_params");
assert!(
u.starts_with("https://mon-projet.aurabase.cloud/v1/auth/oauth/google/start"),
"{u}"
);
assert!(!u.contains("project_id"), "{u}");
}
#[test]
fn est_le_miroir_exact_de_lallowlist_du_backend() {
let chemin = std::path::Path::new("../services/aura-auth/src/handlers/oauth.rs").to_path_buf();
let Ok(texte) = std::fs::read_to_string(&chemin) else {
return;
};
let debut = texte
.find("const OAUTH_FORWARDABLE_PARAMS")
.expect("allowlist backend introuvable dans oauth.rs");
let bloc = &texte[debut..];
let ouverture = bloc.find("= [").expect("littéral du tableau introuvable") + 2;
let bloc = &bloc[ouverture..];
let bloc = &bloc[..bloc.find(']').expect("fermeture du tableau") + 1];
let mut backend: Vec<String> = bloc
.split('"')
.skip(1)
.step_by(2)
.map(str::to_string)
.collect();
backend.sort();
assert!(!backend.is_empty(), "allowlist backend vide : {bloc}");
let mut sdk: Vec<String> = OAUTH_FORWARDABLE_QUERY_PARAMS
.iter()
.map(|s| s.to_string())
.collect();
sdk.sort();
assert_eq!(sdk, backend);
}