diff --git a/Cargo.lock b/Cargo.lock index dd63a0e..e09cf9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1418,6 +1418,31 @@ version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" +[[package]] +name = "headers" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" +dependencies = [ + "base64 0.13.1", + "bitflags 1.3.2", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +dependencies = [ + "http", +] + [[package]] name = "heck" version = "0.4.1" @@ -1960,14 +1985,17 @@ dependencies = [ "matrix-sdk-indexeddb", "matrix-sdk-sled", "mime", + "rand 0.8.5", "reqwest", "ruma", "serde", "serde_json", "thiserror", "tokio", + "tokio-stream", "tracing", "url", + "warp", "wasm-timer", "zeroize", ] @@ -3186,6 +3214,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -3260,6 +3294,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + [[package]] name = "sha2" version = "0.9.9" @@ -3743,6 +3788,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.9" @@ -3796,6 +3852,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -4056,6 +4113,35 @@ dependencies = [ "try-lock", ] +[[package]] +name = "warp" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba431ef570df1287f7f8b07e376491ad54f84d26ac473489427231e1718e1f69" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "headers", + "http", + "hyper", + "log", + "mime", + "mime_guess", + "percent-encoding", + "pin-project", + "rustls-pemfile", + "scoped-tls", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-stream", + "tokio-util", + "tower-service", + "tracing", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 297d5ce..b79152b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,7 +61,7 @@ rev = "f9f0517ed6a6152c1eab36d2e71b11f38831d5e6" [dependencies.matrix-sdk] version = "^0.6.2" default-features = false -features = ["e2e-encryption", "sled", "rustls-tls"] +features = ["e2e-encryption", "sled", "rustls-tls", "sso-login"] [dependencies.tokio] version = "1.24.1" diff --git a/README.md b/README.md index d2957a9..27e8b3e 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ two other TUI clients and Element Web: | Message editing | ✔️ | ✔️ | ❌ | ✔️ | | Room upgrades | ❌ ([#41]) | ✔️ | ❌ | ✔️ | | Localisations | ❌ | 1 | ❌ | 44 | -| SSO Support | ❌ | ✔️ | ✔️ | ✔️ | +| SSO Support | ✔️ | ✔️ | ✔️ | ✔️ | ## License diff --git a/src/main.rs b/src/main.rs index f5b8f5e..2df7c05 100644 --- a/src/main.rs +++ b/src/main.rs @@ -679,9 +679,24 @@ async fn login(worker: Requester, settings: &ApplicationSettings) -> IambResult< } loop { - let password = rpassword::prompt_password("Password: ")?; + println!("Please select login type: [p]assword / [s]ingle sign on"); - match worker.login(LoginStyle::Password(password)) { + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + + let login_style = match input.chars().next().map(|c| c.to_ascii_lowercase()) { + None | Some('p') => { + let password = rpassword::prompt_password("Password: ")?; + LoginStyle::Password(password) + }, + Some('s') => LoginStyle::SingleSignOn, + Some(_) => { + println!("Failed to login. Please enter 'p' or 's'"); + continue; + }, + }; + + match worker.login(login_style) { Ok(info) => { if let Some(msg) = info { println!("{msg}"); diff --git a/src/worker.rs b/src/worker.rs index 2a36dff..bb3beb7 100644 --- a/src/worker.rs +++ b/src/worker.rs @@ -421,6 +421,7 @@ async fn send_receipts_forever(client: &Client, store: &AsyncProgramStore) { pub enum LoginStyle { SessionRestore(Session), Password(String), + SingleSignOn, } pub struct ClientResponse(Receiver); @@ -1071,6 +1072,29 @@ impl ClientWorker { let session = Session::from(resp); serde_json::to_writer(writer, &session).map_err(IambError::from)?; }, + LoginStyle::SingleSignOn => { + let resp = client + .login_sso(|url| { + let opened = format!( + "The following URL should have been opened in your browser:\n {url}" + ); + + async move { + tokio::task::spawn_blocking(move || open::that(url)); + println!("\n{opened}\n"); + Ok(()) + } + }) + .initial_device_display_name(initial_devname().as_str()) + .send() + .await + .map_err(IambError::from)?; + + let file = File::create(self.settings.session_json.as_path())?; + let writer = BufWriter::new(file); + let session = Session::from(resp); + serde_json::to_writer(writer, &session).map_err(IambError::from)?; + }, } self.sync_handle = tokio::spawn(async move {