From 2bbd702ec2e99349ab2ddad87f56479de429cdfc Mon Sep 17 00:00:00 2001 From: Zomatree Date: Tue, 18 Nov 2025 21:33:21 +0000 Subject: [PATCH] feat: sso --- Cargo.lock | 148 +++++++++++++++++++++++- crates/core/config/Cargo.toml | 3 + crates/core/config/Revolt.toml | 1 + crates/core/config/src/lib.rs | 2 + crates/core/database/src/drivers/mod.rs | 3 + crates/delta/src/routes/mod.rs | 4 + crates/delta/src/util/test.rs | 1 + 7 files changed, 156 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index be9eef94..fcdc3bdb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -443,22 +443,25 @@ dependencies = [ [[package]] name = "authifier" version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a03b810b342b4c584cdc1cfc40d1ec763b1d653ef4086f7494740f35d9e1f0" dependencies = [ "async-std", "async-trait", "base32", + "base64 0.22.1", "bson", "chrono", + "form_urlencoded", "futures", "handlebars", "iso8601-timestamp", + "jsonwebtoken", "lazy_static", "lettre", "log", + "mime", "mongodb", "nanoid", + "oauth2-types", "rand 0.8.5", "regex", "reqwest 0.11.27", @@ -469,7 +472,9 @@ dependencies = [ "schemars 0.8.22", "serde", "serde_json", + "serde_urlencoded", "sha1", + "sha2", "totp-lite", "ulid 0.5.0", "validator 0.15.0", @@ -3958,6 +3963,21 @@ dependencies = [ "serde", ] +[[package]] +name = "jsonwebtoken" +version = "9.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" +dependencies = [ + "base64 0.22.1", + "js-sys", + "pem 3.0.5", + "ring", + "serde", + "serde_json", + "simple_asn1", +] + [[package]] name = "jwt-simple" version = "0.11.9" @@ -3976,7 +3996,7 @@ dependencies = [ "p256 0.13.2", "p384", "rand 0.8.5", - "rsa", + "rsa 0.7.2", "serde", "serde_json", "spki 0.6.0", @@ -4168,6 +4188,15 @@ dependencies = [ "log", ] +[[package]] +name = "language-tags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" +dependencies = [ + "serde", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -4518,6 +4547,47 @@ dependencies = [ "tendril", ] +[[package]] +name = "mas-iana" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d41af7e8eb3584b648c563a1b97b8f60c7f3dcd7ea0ded525050418d90c5200" +dependencies = [ + "schemars 0.8.22", + "serde", +] + +[[package]] +name = "mas-jose" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6a1c99221601a1e9ef284efaa6db5985389c839c299d71d5a4c2933ba88eda" +dependencies = [ + "base64ct", + "chrono", + "digest", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", + "generic-array 0.14.7", + "hmac", + "k256", + "mas-iana", + "p256 0.13.2", + "p384", + "rand 0.8.5", + "rsa 0.9.9", + "schemars 0.8.22", + "sec1 0.7.3", + "serde", + "serde_json", + "serde_with", + "sha2", + "signature 2.2.0", + "thiserror 1.0.69", + "tracing", + "url", +] + [[package]] name = "match_cfg" version = "0.1.0" @@ -5002,6 +5072,26 @@ dependencies = [ "libc", ] +[[package]] +name = "oauth2-types" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db9baa46cfc1969e04a7f8c31ee6718a8b4cb52ef31d7d91772f878052d872e1" +dependencies = [ + "chrono", + "data-encoding", + "http 1.3.1", + "language-tags", + "mas-iana", + "mas-jose", + "serde", + "serde_json", + "serde_with", + "sha2", + "thiserror 1.0.69", + "url", +] + [[package]] name = "object" version = "0.36.7" @@ -5449,6 +5539,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der 0.7.10", + "pkcs8 0.10.2", + "spki 0.7.3", +] + [[package]] name = "pkcs8" version = "0.9.0" @@ -6356,6 +6457,7 @@ name = "revolt-config" version = "0.8.9" dependencies = [ "async-std", + "authifier", "cached", "config", "futures-locks", @@ -6848,11 +6950,11 @@ dependencies = [ [[package]] name = "rocket_authifier" version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1f98a5be96ac4144ee1adc809c1594e8212032b8a08d9bc4cef70735dfd976e" dependencies = [ + "async-std", "authifier", "iso8601-timestamp", + "mongodb", "revolt_okapi", "revolt_rocket_okapi", "rocket", @@ -6971,7 +7073,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "pkcs1", + "pkcs1 0.4.1", "pkcs8 0.9.0", "rand_core 0.6.4", "signature 1.6.4", @@ -6980,6 +7082,26 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rsa" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a0376c50d0358279d9d643e4bf7b7be212f1f4ff1da9070a7b54d22ef75c88" +dependencies = [ + "const-oid 0.9.6", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1 0.7.5", + "pkcs8 0.10.2", + "rand_core 0.6.4", + "signature 2.2.0", + "spki 0.7.3", + "subtle", + "zeroize", +] + [[package]] name = "rust-argon2" version = "1.0.1" @@ -7217,11 +7339,13 @@ version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" dependencies = [ + "chrono", "dyn-clone", "indexmap 1.9.3", "schemars_derive", "serde", "serde_json", + "url", ] [[package]] @@ -7813,6 +7937,18 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" +[[package]] +name = "simple_asn1" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" +dependencies = [ + "num-bigint", + "num-traits", + "thiserror 2.0.16", + "time", +] + [[package]] name = "simplecss" version = "0.2.2" diff --git a/crates/core/config/Cargo.toml b/crates/core/config/Cargo.toml index 2a6dbb9e..b253f13a 100644 --- a/crates/core/config/Cargo.toml +++ b/crates/core/config/Cargo.toml @@ -38,3 +38,6 @@ sentry-anyhow = { version = "0.38.1", optional = true } # Core revolt-result = { version = "0.8.9", path = "../result", optional = true } + +# Authifier +authifier = "1.0.15" \ No newline at end of file diff --git a/crates/core/config/Revolt.toml b/crates/core/config/Revolt.toml index 0f264457..cba36495 100644 --- a/crates/core/config/Revolt.toml +++ b/crates/core/config/Revolt.toml @@ -70,6 +70,7 @@ max_concurrent_connections = 50 [api.users] +[api.sso] [pushd] # this changes the names of the queues to not overlap diff --git a/crates/core/config/src/lib.rs b/crates/core/config/src/lib.rs index 5863cbc4..e3f1f472 100644 --- a/crates/core/config/src/lib.rs +++ b/crates/core/config/src/lib.rs @@ -5,6 +5,7 @@ use config::{Config, File, FileFormat}; use futures_locks::RwLock; use once_cell::sync::Lazy; use serde::Deserialize; +use authifier::config::SSO; #[cfg(feature = "sentry")] pub use sentry::{capture_error, capture_message, Level}; @@ -210,6 +211,7 @@ pub struct Api { pub security: ApiSecurity, pub workers: ApiWorkers, pub users: ApiUsers, + pub sso: SSO, } #[derive(Deserialize, Debug, Clone)] diff --git a/crates/core/database/src/drivers/mod.rs b/crates/core/database/src/drivers/mod.rs index 2a2c7b85..b951c96e 100644 --- a/crates/core/database/src/drivers/mod.rs +++ b/crates/core/database/src/drivers/mod.rs @@ -209,6 +209,8 @@ impl Database { } else { EmailVerificationConfig::Disabled }, + sso: config.api.sso.clone(), + server_url: Some(config.hosts.api.parse().expect("Failed to parse API host url.")), ..Default::default() }; @@ -244,6 +246,7 @@ impl Database { event_channel: Some(crate::tasks::authifier_relay::sender()), #[cfg(not(feature = "tasks"))] event_channel: None, + ..Default::default() } } } diff --git a/crates/delta/src/routes/mod.rs b/crates/delta/src/routes/mod.rs index 9643a365..03ab2c6c 100644 --- a/crates/delta/src/routes/mod.rs +++ b/crates/delta/src/routes/mod.rs @@ -36,6 +36,7 @@ pub fn mount(config: Settings, mut rocket: Rocket) -> Rocket { "/auth/account" => rocket_authifier::routes::account::routes(), "/auth/session" => rocket_authifier::routes::session::routes(), "/auth/mfa" => rocket_authifier::routes::mfa::routes(), + "/auth/sso" => rocket_authifier::routes::sso::routes(), "/onboard" => onboard::routes(), "/policy" => policy::routes(), "/push" => push::routes(), @@ -57,6 +58,7 @@ pub fn mount(config: Settings, mut rocket: Rocket) -> Rocket { "/auth/account" => rocket_authifier::routes::account::routes(), "/auth/session" => rocket_authifier::routes::session::routes(), "/auth/mfa" => rocket_authifier::routes::mfa::routes(), + "/auth/sso" => rocket_authifier::routes::sso::routes(), "/onboard" => onboard::routes(), "/policy" => policy::routes(), "/push" => push::routes(), @@ -79,6 +81,7 @@ pub fn mount(config: Settings, mut rocket: Rocket) -> Rocket { "/auth/account" => rocket_authifier::routes::account::routes(), "/auth/session" => rocket_authifier::routes::session::routes(), "/auth/mfa" => rocket_authifier::routes::mfa::routes(), + "/auth/sso" => rocket_authifier::routes::sso::routes(), "/onboard" => onboard::routes(), "/push" => push::routes(), "/sync" => sync::routes(), @@ -99,6 +102,7 @@ pub fn mount(config: Settings, mut rocket: Rocket) -> Rocket { "/auth/account" => rocket_authifier::routes::account::routes(), "/auth/session" => rocket_authifier::routes::session::routes(), "/auth/mfa" => rocket_authifier::routes::mfa::routes(), + "/auth/sso" => rocket_authifier::routes::sso::routes(), "/onboard" => onboard::routes(), "/push" => push::routes(), "/sync" => sync::routes() diff --git a/crates/delta/src/util/test.rs b/crates/delta/src/util/test.rs index 067f8bd0..f35d4a5a 100644 --- a/crates/delta/src/util/test.rs +++ b/crates/delta/src/util/test.rs @@ -104,6 +104,7 @@ impl TestHarness { mfa: Default::default(), password_reset: None, verification: EmailVerification::Verified, + id_providers: Default::default(), }; self.authifier