SSO is working now

This commit is contained in:
0xf8 2023-04-21 16:22:14 -04:00
parent 1c5565e0fb
commit db61e1b78d
Signed by: 0xf8
GPG Key ID: 446580D758689584
3 changed files with 191 additions and 50 deletions

150
Cargo.lock generated
View File

@ -912,6 +912,31 @@ dependencies = [
"ahash", "ahash",
] ]
[[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",
"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]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.2.6" version = "0.2.6"
@ -1096,6 +1121,25 @@ version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
[[package]]
name = "is-docker"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3"
dependencies = [
"once_cell",
]
[[package]]
name = "is-wsl"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5"
dependencies = [
"is-docker",
"once_cell",
]
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.10.5" version = "0.10.5"
@ -1214,14 +1258,17 @@ dependencies = [
"matrix-sdk-indexeddb", "matrix-sdk-indexeddb",
"matrix-sdk-sled", "matrix-sdk-sled",
"mime", "mime",
"rand 0.8.5",
"reqwest", "reqwest",
"ruma", "ruma",
"serde", "serde",
"serde_json", "serde_json",
"thiserror", "thiserror",
"tokio", "tokio",
"tokio-stream",
"tracing", "tracing",
"url", "url",
"warp",
"wasm-timer", "wasm-timer",
"zeroize", "zeroize",
] ]
@ -1390,6 +1437,16 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mime_guess"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
dependencies = [
"mime",
"unicase",
]
[[package]] [[package]]
name = "mio" name = "mio"
version = "0.8.6" version = "0.8.6"
@ -1442,6 +1499,16 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "open"
version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "873240a4a404d44c8cd1bf394359245d466a5695771fea15a79cafbc5e5cf4d7"
dependencies = [
"is-wsl",
"pathdiff",
]
[[package]] [[package]]
name = "openssl" name = "openssl"
version = "0.10.50" version = "0.10.50"
@ -1545,6 +1612,12 @@ dependencies = [
"subtle", "subtle",
] ]
[[package]]
name = "pathdiff"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
[[package]] [[package]]
name = "pbkdf2" name = "pbkdf2"
version = "0.11.0" version = "0.11.0"
@ -2100,6 +2173,15 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "rustls-pemfile"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
dependencies = [
"base64 0.21.0",
]
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.13" version = "1.0.13"
@ -2115,6 +2197,7 @@ dependencies = [
"dirs", "dirs",
"matrix-sdk", "matrix-sdk",
"once_cell", "once_cell",
"open",
"rand 0.8.5", "rand 0.8.5",
"reqwest", "reqwest",
"rpassword", "rpassword",
@ -2135,6 +2218,12 @@ dependencies = [
"windows-sys 0.42.0", "windows-sys 0.42.0",
] ]
[[package]]
name = "scoped-tls"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.1.0" version = "1.1.0"
@ -2216,6 +2305,17 @@ dependencies = [
"serde", "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.6",
]
[[package]] [[package]]
name = "sha2" name = "sha2"
version = "0.9.9" version = "0.9.9"
@ -2473,6 +2573,17 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "tokio-stream"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313"
dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
]
[[package]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.7" version = "0.7.7"
@ -2526,6 +2637,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"log",
"pin-project-lite", "pin-project-lite",
"tracing-attributes", "tracing-attributes",
"tracing-core", "tracing-core",
@ -2563,6 +2675,15 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]]
name = "unicase"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
dependencies = [
"version_check",
]
[[package]] [[package]]
name = "unicode-bidi" name = "unicode-bidi"
version = "0.3.13" version = "0.3.13"
@ -2686,6 +2807,35 @@ dependencies = [
"try-lock", "try-lock",
] ]
[[package]]
name = "warp"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27e1a710288f0f91a98dd8a74f05b76a10768db245ce183edf64dc1afdc3016c"
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]] [[package]]
name = "wasi" name = "wasi"
version = "0.9.0+wasi-snapshot-preview1" version = "0.9.0+wasi-snapshot-preview1"

View File

@ -10,8 +10,9 @@ authors = [ "@0xf8:projectsegfau.lt", "@jjj333:pain.agency" ]
anyhow = "1.0.70" anyhow = "1.0.70"
argparse = "0.2.2" argparse = "0.2.2"
dirs = "5.0.0" dirs = "5.0.0"
matrix-sdk = "0.6.2" matrix-sdk = { version = "0.6.2", features = [ "sso-login" ] }
once_cell = "1.17.1" once_cell = "1.17.1"
open = "4.0.2"
rand = "0.8.5" rand = "0.8.5"
reqwest = "0.11.16" reqwest = "0.11.16"
rpassword = "7.2.0" rpassword = "7.2.0"

View File

@ -32,7 +32,7 @@ enum LoginChoice {
} }
impl LoginChoice { impl LoginChoice {
pub async fn login(&self, client: &Client, user: String, hs: String) -> anyhow::Result<Client> { pub async fn login(&self, client: &Client, user: String, hs: String) -> anyhow::Result<()> {
match self { match self {
LoginChoice::Password => Self::login_password(client, user, hs).await, LoginChoice::Password => Self::login_password(client, user, hs).await,
LoginChoice::Sso => Self::login_sso(client, None).await, LoginChoice::Sso => Self::login_sso(client, None).await,
@ -40,7 +40,7 @@ impl LoginChoice {
} }
} }
async fn login_password(client: &Client, user: String, _hs: String) -> anyhow::Result<Client> { async fn login_password(client: &Client, user: String, _hs: String) -> anyhow::Result<()> {
loop { loop {
let password = prompt_password("Password\n> ")?; let password = prompt_password("Password\n> ")?;
@ -52,7 +52,7 @@ impl LoginChoice {
{ {
Ok(_) => { Ok(_) => {
println!("[*] Logged in as {user}"); println!("[*] Logged in as {user}");
return Ok(client.to_owned()); break;
} }
Err(e) => { Err(e) => {
println!("[!] Error logging in: {e}"); println!("[!] Error logging in: {e}");
@ -60,40 +60,27 @@ impl LoginChoice {
} }
} }
} }
Ok(())
} }
async fn login_sso(client: &Client, idp: Option<IdentityProvider>) -> anyhow::Result<Client> { async fn login_sso(client: &Client, idp: Option<IdentityProvider>) -> anyhow::Result<()> {
println!("Warning! SSO is a work in progress. Do not expect it to work."); let mut login_builder = client.login_sso(|url| async move {
open::that_in_background(url);
println!("[*] Waiting for SSO token...");
Ok(())
}).initial_device_display_name("scam-police");
if let Some(idp) = idp.to_owned() {
login_builder = login_builder.identity_provider_id(&idp.id);
let redirect_url = String::new(); login_builder.send().await?;
let token = if let Some(idp) = idp {
client.get_sso_login_url(&redirect_url, Some(&idp.id)).await
} else { } else {
client.get_sso_login_url(&redirect_url, None).await login_builder.send().await?;
};
println!("{redirect_url:?}, {token:?}");
match token {
Ok(t) => {
match client
.login_token(&t)
.initial_device_display_name("scam-police")
.send()
.await {
Ok(_) => {
Ok(client.to_owned())
}
Err(e) => {
anyhow::bail!("{e}")
}
}
},
Err(e) => {
anyhow::bail!("Failed to get SSO token: {e}")
}
} }
println!("[+] Got SSO token!");
Ok(())
} }
} }
@ -102,7 +89,7 @@ impl LoginChoice {
// //
pub async fn login(data_dir: &Path, session_file: &Path, mxid: String) -> anyhow::Result<Client> { pub async fn login(data_dir: &Path, session_file: &Path, mxid: String) -> anyhow::Result<Client> {
println!("[*] No previous session, logging in with mxid..."); println!("[*] Logging in as {mxid}...");
let (user, hs) = resolve_mxid(mxid).await?; let (user, hs) = resolve_mxid(mxid).await?;
let (client, client_session) = build_client(data_dir, hs.to_owned()).await?; let (client, client_session) = build_client(data_dir, hs.to_owned()).await?;
@ -125,45 +112,48 @@ pub async fn login(data_dir: &Path, session_file: &Path, mxid: String) -> anyhow
} }
} }
let client = match login_choices.to_owned().len() { match login_choices.to_owned().len() {
0 => anyhow::bail!("No supported login types"), 0 => anyhow::bail!("No supported login types"),
1 => login_choices.to_owned().get(0).unwrap().login(&client, user, hs.to_owned()).await, 1 => login_choices.to_owned().get(0).unwrap().login(&client, user, hs.to_owned()).await,
_ => { _ => {
use terminal_menu::*; use terminal_menu::*;
let mut menu_items = vec![label("-- Scam Police Login --")]; let mut menu_items = vec![label("----- Scam Police Login -----")];
let choices: Vec<(LoginChoice, String)> = login_choices.into_iter().map(|a| (a.to_owned(), match a { let choices: Vec<(LoginChoice, String)> = login_choices.into_iter().map(|a| (a.to_owned(), match a {
LoginChoice::Password => format!("Password"), LoginChoice::Password => format!("Password"),
LoginChoice::Sso => format!("SSO"), LoginChoice::Sso => format!("SSO"),
LoginChoice::SsoIdp(idp) => format!("SSO ({})", idp.name), LoginChoice::SsoIdp(idp) => format!("SSO via {}", idp.name),
})).collect(); })).collect();
for choice in choices.to_owned() { for choice in choices.to_owned() {
menu_items.push(button(choice.1)); menu_items.push(button(choice.1));
} }
menu_items.push(button("Abort login"));
menu_items.push(label("-----------------------------"));
let menu = menu(menu_items); let menu = menu(menu_items);
run(&menu); run(&menu);
let menu = mut_menu(&menu); let menu = mut_menu(&menu);
let mut selected: Option<LoginChoice> = None; let mut selected: Option<LoginChoice> = None;
let name = menu.selected_item_name().to_string(); let name = menu.selected_item_name().to_string();
for c in choices { if name == "Abort login" {
if c.1 == name { selected = None;
selected = Some(c.0.to_owned()); } else {
for c in choices {
if c.1 == name {
selected = Some(c.0.to_owned());
}
} }
} }
match selected { match selected {
Some(s) => s.login(&client, user, hs.to_owned()).await, Some(s) => s.login(&client, user, hs.to_owned()).await,
None => anyhow::bail!("Invalid selection, aborting login") None => anyhow::bail!("Aborting login")
} }
} }
}; }?;
let client = match client {
Ok(client) => client,
Err(e) => anyhow::bail!("{e}")
};
let user_session = client let user_session = client
.session() .session()
@ -201,7 +191,7 @@ pub async fn build_client(data_dir: &Path, hs: String) -> anyhow::Result<(Client
.await .await
{ {
Ok(client) => { Ok(client) => {
println!("[*] Homeserver OK"); println!("[+] Homeserver OK");
return Ok(( return Ok((
client, client,
ClientSession { ClientSession {
@ -277,7 +267,7 @@ pub async fn sync<'a>(
client: Client, client: Client,
initial_sync_token: Option<String>, initial_sync_token: Option<String>,
) -> anyhow::Result<(Client, SyncSettings<'a>)> { ) -> anyhow::Result<(Client, SyncSettings<'a>)> {
println!("[*] Initial sync..."); println!("[*] Running initial sync...");
let filter = FilterDefinition::empty(); let filter = FilterDefinition::empty();
@ -304,7 +294,7 @@ pub async fn sync<'a>(
} }
} }
println!("[*] The bot is ready!"); println!("[*] Scam police is now running!");
Ok((client, sync_settings)) Ok((client, sync_settings))
} }