Passwords and refresh tokens go only to the system keychain; a refused keychain keeps them in memory until exit and says why. Gmail and Microsoft sign in by authorization code with S256 PKCE on a loopback redirect; refresh tokens are kept, and revoked grants ask to sign in again. Client IDs come from the build (env or oauth.env). ureq trace records never reach the log. Co-Authored-By: Claude <noreply@anthropic.com>
46 lines
1.4 KiB
Rust
46 lines
1.4 KiB
Rust
//! The real logger at trace, around token requests.
|
|
mod oauth_fake;
|
|
|
|
use ely_mail_engine::oauth::refresh;
|
|
use ely_platform::AppId;
|
|
use oauth_fake::{endpoint, provider, signed_in};
|
|
|
|
const SECRET: &str = "PRIVATE_SECRET";
|
|
const CODE_TOKEN: &str = "PRIVATE_FIRST";
|
|
const ROTATED: &str = "PRIVATE_ROTATED";
|
|
|
|
#[tokio::test]
|
|
async fn trace_logs_keep_no_token_or_client_secret() {
|
|
let dir = tempfile::tempdir().unwrap();
|
|
// The only test here; no thread reads env.
|
|
unsafe { std::env::set_var("ELY_LOG", "trace") };
|
|
ely_platform::logging::init_in(AppId::Mail, dir.path()).unwrap();
|
|
|
|
let body = format!(
|
|
r#"{{"access_token":"{CODE_TOKEN}","expires_in":60,"refresh_token":"{CODE_TOKEN}"}}"#
|
|
);
|
|
signed_in(body).await.unwrap();
|
|
let body =
|
|
format!(r#"{{"access_token":"{ROTATED}","expires_in":60,"refresh_token":"{ROTATED}"}}"#);
|
|
let (token, _) = endpoint(200, body);
|
|
refresh(&provider(token, Some(SECRET)), CODE_TOKEN)
|
|
.await
|
|
.unwrap();
|
|
|
|
log::logger().flush();
|
|
let logged = std::fs::read_to_string(dir.path().join("ely.log")).unwrap();
|
|
assert!(logged.contains("oauth: test token granted"), "{logged}");
|
|
for secret in [SECRET, CODE_TOKEN, ROTATED, "PRIVATE"] {
|
|
assert!(
|
|
!logged.contains(secret),
|
|
"{secret} reached the log:
|
|
{logged}"
|
|
);
|
|
}
|
|
assert!(
|
|
!logged.contains(" ureq"),
|
|
"HTTP library logged:
|
|
{logged}"
|
|
);
|
|
}
|