From 37bc36e551be7b93771bca4e40e9d35a2b7f5254 Mon Sep 17 00:00:00 2001 From: f00wl Date: Wed, 13 Dec 2023 16:02:38 +0100 Subject: [PATCH 1/2] feat(auth): support SSO login * add sso-login to matrix-sdk features * make password args optional * try SSO login if no password provided * update Readme --- Cargo.lock | 24 ++++++++++++++++++++++++ Cargo.toml | 4 ++-- Readme.md | 14 ++++++++++---- src/main.rs | 37 ++++++++++++++++++++++++++++++------- 4 files changed, 66 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ed806c4..65eec8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1235,6 +1235,7 @@ dependencies = [ "futures-util", "gloo-timers", "http", + "hyper", "im", "indexmap", "matrix-sdk-base", @@ -1243,6 +1244,7 @@ dependencies = [ "matrix-sdk-sled", "mime", "pin-project-lite", + "rand 0.8.5", "reqwest", "ruma", "serde", @@ -1250,6 +1252,7 @@ dependencies = [ "serde_json", "thiserror", "tokio", + "tower", "tracing", "url", "zeroize", @@ -2449,6 +2452,26 @@ dependencies = [ "winnow", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-util", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -2462,6 +2485,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", + "log", "pin-project-lite", "tracing-attributes", "tracing-core", diff --git a/Cargo.toml b/Cargo.toml index e2739b5..558d9a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,9 +11,9 @@ env_logger = "0.10.0" log = "0.4.8" futures = "0.3.26" clap = { version = "4.1.6", features = ["derive", "env"] } -tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] } +tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] } [dependencies.matrix-sdk] git = "https://github.com/matrix-org/matrix-rust-sdk" ref = "e162c99" -features = ["anyhow"] +features = ["anyhow", "sso-login"] diff --git a/Readme.md b/Readme.md index 90e05ba..303351a 100644 --- a/Readme.md +++ b/Readme.md @@ -5,6 +5,7 @@ CLI to migrate one matrix account to a new one. Similar to [the EMS migrator][em 1. is a nice little CLI tool, based on `matrix-rust-sdk` 2. allows for restarts (refreshes at the beginning) 3. it runs the operations async and is thus a lot faster +4. SSO authentication is supported _Note_: It currently only migrates the rooms listing and power_levels, no user settings or profile data. @@ -26,10 +27,15 @@ matrix-migrate ### Usage note -It requires both the user and password for the user `from` and `to` either as -command line parameters, or preferably as environment variables (`FROM_USER=`, -`FROM_PASSWORD`). It uses matrix discovery but if that doesn't work for you -you can provide custom homeservers, too. +Password authentication requires both the user and password for the user `from` +and `to` either as command line parameters, or preferably as environment +variables (`FROM_USER=`, `FROM_PASSWORD`). + +If no `from` and/or `to` password provided it will try login with servers's +SSO. + +It uses matrix discovery but if that doesn't work for you, you can provide +custom homeservers, too. It will start with a full-sync of the room state, so depending on the size of your matrix account(s), this may take a moment. diff --git a/src/main.rs b/src/main.rs index a5a53c8..8671fea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,7 +22,7 @@ struct Args { /// Password of the account to migrate from #[arg(long = "from-pw", env = "FROM_PASSWORD")] - from_user_password: String, + from_user_password: Option, /// Custom homeserver, if not defined discovery is used #[arg(long, env = "FROM_HOMESERVER")] @@ -34,7 +34,7 @@ struct Args { /// Password of the account to migrate from #[arg(long = "to-pw", env = "TO_PASSWORD")] - to_user_password: String, + to_user_password: Option, /// Custom homeserver, if not defined discovery is used #[arg(long, env = "TO_HOMESERVER")] @@ -62,10 +62,22 @@ async fn main() -> anyhow::Result<()> { info!("Logging in {:}", args.from_user); - from_c - .login_username(args.from_user, &args.from_user_password) - .send() - .await?; + if args.from_user_password.is_none() { + info!("No password given, trying SSO authtentication."); + from_c + .login_sso(|sso_url| async move { + println!("Open this URL in a web browser {:}", sso_url); + Ok(()) + }) + .initial_device_display_name("matrix-migrate") + .send() + .await?; + } else { + from_c + .login_username(args.from_user, &args.from_user_password.unwrap()) + .send() + .await?; + }; let to_cb = Client::builder().user_agent("matrix-migrate/1"); let to_c = if let Some(h) = args.to_homeserver { @@ -79,9 +91,20 @@ async fn main() -> anyhow::Result<()> { info!("Logging in {:}", args.to_user); - to_c.login_username(args.to_user, &args.to_user_password) + if args.to_user_password.is_none() { + info!("No password given, trying SSO authtentication."); + to_c.login_sso(|sso_url| async move { + println!("Open this URL in a web browser {:}", sso_url); + Ok(()) + }) + .initial_device_display_name("matrix-migrate") .send() .await?; + } else { + to_c.login_username(args.to_user, &args.to_user_password.unwrap()) + .send() + .await?; + } info!("All logged in. Syncing..."); From 5d4f405c2885182bb1fca638b2fbea852011435e Mon Sep 17 00:00:00 2001 From: f00wl Date: Wed, 13 Dec 2023 16:23:14 +0100 Subject: [PATCH 2/2] refactor(log): use info instead of println * use info! log to print SSO login URL * fix typo btw --- src/main.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8671fea..522818f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -63,10 +63,10 @@ async fn main() -> anyhow::Result<()> { info!("Logging in {:}", args.from_user); if args.from_user_password.is_none() { - info!("No password given, trying SSO authtentication."); + info!("No password provided, trying SSO authtentication."); from_c .login_sso(|sso_url| async move { - println!("Open this URL in a web browser {:}", sso_url); + info!("Open this URL in a web browser {:}", sso_url); Ok(()) }) .initial_device_display_name("matrix-migrate") @@ -92,9 +92,9 @@ async fn main() -> anyhow::Result<()> { info!("Logging in {:}", args.to_user); if args.to_user_password.is_none() { - info!("No password given, trying SSO authtentication."); + info!("No password provided, trying SSO authtentication."); to_c.login_sso(|sso_url| async move { - println!("Open this URL in a web browser {:}", sso_url); + info!("Open this URL in a web browser {:}", sso_url); Ok(()) }) .initial_device_display_name("matrix-migrate")