Browse Source

sso with openid connect

merge-requests/80/head
Bruno Bigras 5 years ago
parent
commit
d336c0acff
  1. 457
      Cargo.lock
  2. 6
      Cargo.toml
  3. 7
      conduit-example.toml
  4. 2
      src/client_server/mod.rs
  5. 110
      src/client_server/session.rs
  6. 188
      src/client_server/sso.rs
  7. 14
      src/database.rs
  8. 26
      src/database/globals.rs
  9. 4
      src/main.rs

457
Cargo.lock generated

@ -8,6 +8,60 @@ version = "1.2.0" @@ -8,6 +8,60 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
[[package]]
name = "aead"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331"
dependencies = [
"generic-array",
]
[[package]]
name = "aes"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561"
dependencies = [
"aes-soft",
"aesni",
"cipher",
]
[[package]]
name = "aes-gcm"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da"
dependencies = [
"aead",
"aes",
"cipher",
"ctr",
"ghash",
"subtle",
]
[[package]]
name = "aes-soft"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072"
dependencies = [
"cipher",
"opaque-debug",
]
[[package]]
name = "aesni"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce"
dependencies = [
"cipher",
"opaque-debug",
]
[[package]]
name = "ahash"
version = "0.7.4"
@ -146,6 +200,21 @@ dependencies = [ @@ -146,6 +200,21 @@ dependencies = [
"serde",
]
[[package]]
name = "biscuit"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dee631cea28b00e115fd355a1adedc860b155096941dc01259969eabd434a37"
dependencies = [
"chrono",
"data-encoding",
"num",
"once_cell",
"ring",
"serde",
"serde_json",
]
[[package]]
name = "bitflags"
version = "1.3.2"
@ -226,10 +295,20 @@ dependencies = [ @@ -226,10 +295,20 @@ dependencies = [
"libc",
"num-integer",
"num-traits",
"serde",
"time 0.1.43",
"winapi",
]
[[package]]
name = "cipher"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801"
dependencies = [
"generic-array",
]
[[package]]
name = "color_quant"
version = "1.1.0"
@ -242,15 +321,18 @@ version = "0.2.0" @@ -242,15 +321,18 @@ version = "0.2.0"
dependencies = [
"base64 0.13.0",
"bytes",
"chrono",
"crossbeam",
"directories",
"heed",
"hmac",
"hmac 0.11.0",
"http",
"image",
"jsonwebtoken",
"lru-cache",
"macaroon",
"num_cpus",
"openid",
"opentelemetry",
"opentelemetry-jaeger",
"parking_lot",
@ -277,6 +359,7 @@ dependencies = [ @@ -277,6 +359,7 @@ dependencies = [
"tracing-flame",
"tracing-subscriber",
"trust-dns-resolver",
"uuid",
"webpki 0.22.0",
]
@ -304,7 +387,13 @@ version = "0.15.1" @@ -304,7 +387,13 @@ version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5f1c7727e460397e56abc4bddc1d49e07a1ad78fc98eb2e1c8f032a58a2f80d"
dependencies = [
"aes-gcm",
"base64 0.13.0",
"hkdf",
"percent-encoding",
"rand 0.8.4",
"sha2",
"subtle",
"time 0.2.27",
"version_check",
]
@ -334,6 +423,12 @@ dependencies = [ @@ -334,6 +423,12 @@ dependencies = [
"libc",
]
[[package]]
name = "cpuid-bool"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba"
[[package]]
name = "crc32fast"
version = "1.2.1"
@ -430,6 +525,16 @@ dependencies = [ @@ -430,6 +525,16 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "crypto-mac"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a"
dependencies = [
"generic-array",
"subtle",
]
[[package]]
name = "crypto-mac"
version = "0.11.1"
@ -440,6 +545,15 @@ dependencies = [ @@ -440,6 +545,15 @@ dependencies = [
"subtle",
]
[[package]]
name = "ctr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f"
dependencies = [
"cipher",
]
[[package]]
name = "curve25519-dalek"
version = "3.2.0"
@ -634,6 +748,21 @@ version = "1.0.7" @@ -634,6 +748,21 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
version = "1.0.1"
@ -802,6 +931,16 @@ dependencies = [ @@ -802,6 +931,16 @@ dependencies = [
"wasi 0.10.2+wasi-snapshot-preview1",
]
[[package]]
name = "ghash"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375"
dependencies = [
"opaque-debug",
"polyval",
]
[[package]]
name = "gif"
version = "0.11.2"
@ -909,13 +1048,33 @@ dependencies = [ @@ -909,13 +1048,33 @@ dependencies = [
"libc",
]
[[package]]
name = "hkdf"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f"
dependencies = [
"digest",
"hmac 0.10.1",
]
[[package]]
name = "hmac"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15"
dependencies = [
"crypto-mac 0.10.1",
"digest",
]
[[package]]
name = "hmac"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
dependencies = [
"crypto-mac",
"crypto-mac 0.11.1",
"digest",
]
@ -1003,6 +1162,19 @@ dependencies = [ @@ -1003,6 +1162,19 @@ dependencies = [
"webpki 0.21.4",
]
[[package]]
name = "hyper-tls"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
dependencies = [
"bytes",
"hyper",
"native-tls",
"tokio",
"tokio-native-tls",
]
[[package]]
name = "idna"
version = "0.2.3"
@ -1014,6 +1186,12 @@ dependencies = [ @@ -1014,6 +1186,12 @@ dependencies = [
"unicode-normalization",
]
[[package]]
name = "if_chain"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
[[package]]
name = "image"
version = "0.23.14"
@ -1173,6 +1351,18 @@ version = "0.2.101" @@ -1173,6 +1351,18 @@ version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21"
[[package]]
name = "libsodium-sys"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b779387cd56adfbc02ea4a668e704f729be8d6a6abd2c27ca5ee537849a92fd"
dependencies = [
"cc",
"libc",
"pkg-config",
"walkdir",
]
[[package]]
name = "libsqlite3-sys"
version = "0.22.2"
@ -1241,6 +1431,18 @@ dependencies = [ @@ -1241,6 +1431,18 @@ dependencies = [
"linked-hash-map",
]
[[package]]
name = "macaroon"
version = "0.1.1"
source = "git+https://github.com/macaroon-rs/macaroon.git?branch=trunk#74cc7b50c04fcd2ca468d28d6bc9a155f26fa047"
dependencies = [
"base64 0.12.3",
"log",
"serde",
"serde_json",
"sodiumoxide",
]
[[package]]
name = "maplit"
version = "1.0.2"
@ -1340,6 +1542,24 @@ dependencies = [ @@ -1340,6 +1542,24 @@ dependencies = [
"version_check",
]
[[package]]
name = "native-tls"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d"
dependencies = [
"lazy_static",
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
]
[[package]]
name = "ntapi"
version = "0.3.6"
@ -1349,6 +1569,20 @@ dependencies = [ @@ -1349,6 +1569,20 @@ dependencies = [
"winapi",
]
[[package]]
name = "num"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
dependencies = [
"num-bigint 0.3.3",
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.2.6"
@ -1360,6 +1594,26 @@ dependencies = [ @@ -1360,6 +1594,26 @@ dependencies = [
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
dependencies = [
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.44"
@ -1388,6 +1642,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1388,6 +1642,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
dependencies = [
"autocfg",
"num-bigint 0.3.3",
"num-integer",
"num-traits",
]
@ -1423,12 +1678,57 @@ version = "0.3.0" @@ -1423,12 +1678,57 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "openid"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab30a9456b3484c408d9708b6f65b2bd834fdf22b73567775e1ca6de5524dd19"
dependencies = [
"base64 0.13.0",
"biscuit",
"chrono",
"lazy_static",
"reqwest",
"serde",
"serde_json",
"thiserror",
"url",
"validator",
]
[[package]]
name = "openssl"
version = "0.10.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95"
dependencies = [
"bitflags",
"cfg-if 1.0.0",
"foreign-types",
"libc",
"once_cell",
"openssl-sys",
]
[[package]]
name = "openssl-probe"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a"
[[package]]
name = "openssl-sys"
version = "0.9.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7df13d165e607909b363a4757a6f133f8a818a74e9d3a98d09c6128e15fa4c73"
dependencies = [
"autocfg",
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "opentelemetry"
version = "0.16.0"
@ -1623,6 +1923,17 @@ dependencies = [ @@ -1623,6 +1923,17 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "polyval"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eebcc4aa140b9abd2bc40d9c3f7ccec842679cd79045ac3a7ac698c1a064b7cd"
dependencies = [
"cpuid-bool",
"opaque-debug",
"universal-hash",
]
[[package]]
name = "ppv-lite86"
version = "0.2.10"
@ -1639,6 +1950,30 @@ dependencies = [ @@ -1639,6 +1950,30 @@ dependencies = [
"toml",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.19"
@ -1858,18 +2193,22 @@ dependencies = [ @@ -1858,18 +2193,22 @@ dependencies = [
"http-body",
"hyper",
"hyper-rustls",
"hyper-tls",
"ipnet",
"js-sys",
"lazy_static",
"log",
"mime",
"native-tls",
"percent-encoding",
"pin-project-lite",
"rustls",
"rustls-native-certs",
"serde",
"serde_json",
"serde_urlencoded",
"tokio",
"tokio-native-tls",
"tokio-rustls",
"tokio-socks",
"url",
@ -2319,6 +2658,15 @@ version = "1.0.5" @@ -2319,6 +2658,15 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "schannel"
version = "0.1.19"
@ -2415,6 +2763,7 @@ version = "1.0.67" @@ -2415,6 +2763,7 @@ version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7f9e390c27c3c0ce8bc5d725f6e4d30a29d26659494aa4b17535f7522c5c950"
dependencies = [
"indexmap",
"itoa",
"ryu",
"serde",
@ -2507,7 +2856,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2507,7 +2856,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692ca13de57ce0613a363c8c2f1de925adebc81b04c923ac60c5488bb44abe4b"
dependencies = [
"chrono",
"num-bigint",
"num-bigint 0.2.6",
"num-traits",
]
@ -2561,6 +2910,18 @@ dependencies = [ @@ -2561,6 +2910,18 @@ dependencies = [
"winapi",
]
[[package]]
name = "sodiumoxide"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e26be3acb6c2d9a7aac28482586a7856436af4cfe7100031d219de2d2ecb0028"
dependencies = [
"ed25519",
"libc",
"libsodium-sys",
"serde",
]
[[package]]
name = "spin"
version = "0.5.2"
@ -2854,6 +3215,16 @@ dependencies = [ @@ -2854,6 +3215,16 @@ dependencies = [
"syn",
]
[[package]]
name = "tokio-native-tls"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
dependencies = [
"native-tls",
"tokio",
]
[[package]]
name = "tokio-rustls"
version = "0.22.0"
@ -3128,6 +3499,16 @@ version = "0.1.7" @@ -3128,6 +3499,16 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7"
[[package]]
name = "universal-hash"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
dependencies = [
"generic-array",
"subtle",
]
[[package]]
name = "untrusted"
version = "0.7.1"
@ -3144,8 +3525,58 @@ dependencies = [ @@ -3144,8 +3525,58 @@ dependencies = [
"idna",
"matches",
"percent-encoding",
"serde",
]
[[package]]
name = "uuid"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
dependencies = [
"getrandom 0.2.3",
"serde",
]
[[package]]
name = "validator"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d6937c33ec6039d8071bcf72933146b5bbe378d645d8fa59bdadabfc2a249"
dependencies = [
"idna",
"lazy_static",
"regex",
"serde",
"serde_derive",
"serde_json",
"url",
"validator_derive",
"validator_types",
]
[[package]]
name = "validator_derive"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4286b4497f270f59276a89ae0ad109d5f8f18c69b613e3fb22b61201aadb0c4d"
dependencies = [
"if_chain",
"lazy_static",
"proc-macro-error",
"proc-macro2",
"quote",
"regex",
"syn",
"validator_types",
]
[[package]]
name = "validator_types"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad9680608df133af2c1ddd5eaf1ddce91d60d61b6bc51494ef326458365a470a"
[[package]]
name = "vcpkg"
version = "0.2.15"
@ -3158,6 +3589,17 @@ version = "0.9.3" @@ -3158,6 +3589,17 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "walkdir"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
dependencies = [
"same-file",
"winapi",
"winapi-util",
]
[[package]]
name = "want"
version = "0.3.0"
@ -3312,6 +3754,15 @@ version = "0.4.0" @@ -3312,6 +3754,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"

6
Cargo.toml

@ -12,10 +12,11 @@ edition = "2018" @@ -12,10 +12,11 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
chrono = "0.4"
# Used to handle requests
# TODO: This can become optional as soon as proper configs are supported
# rocket = { git = "https://github.com/SergioBenitez/Rocket.git", rev = "801e04bd5369eb39e126c75f6d11e1e9597304d8", features = ["tls"] } # Used to handle requests
rocket = { version = "0.5.0-rc.1", features = ["tls"] } # Used to handle requests
rocket = { version = "0.5.0-rc.1", features = ["tls", "secrets"] } # Used to handle requests
# Used for matrix spec type definitions and helpers
#ruma = { version = "0.4.0", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
@ -35,6 +36,8 @@ bytes = "1.1.0" @@ -35,6 +36,8 @@ bytes = "1.1.0"
http = "0.2.4"
# Used to find data directory for default db path
directories = "3.0.2"
macaroon = { git = "https://github.com/macaroon-rs/macaroon.git", branch = "trunk" }
openid = "0.9"
# Used for ruma wrapper
serde_json = { version = "1.0.67", features = ["raw_value"] }
# Used for appservice registration files
@ -82,6 +85,7 @@ thread_local = "1.1.3" @@ -82,6 +85,7 @@ thread_local = "1.1.3"
# used for TURN server authentication
hmac = "0.11.0"
sha-1 = "0.9.8"
uuid = { version = "0.8", features = ["serde", "v4"] }
[features]
default = ["conduit_bin", "backend_sqlite"]

7
conduit-example.toml

@ -46,3 +46,10 @@ proxy = "none" # more examples can be found at src/database/proxy.rs:6 @@ -46,3 +46,10 @@ proxy = "none" # more examples can be found at src/database/proxy.rs:6
# The total amount of memory that the database will use.
#db_cache_capacity_mb = 200
[default.openid]
client_id = "conduit"
secret = "00000000-0000-0000-0000-000000000000"
discover_url = "https://keycloak.domain.com/auth/realms/Realm_name"
redirect_url = "http://localhost:8080/sso_return"
macaroon_key = "this is the key"

2
src/client_server/mod.rs

@ -20,6 +20,7 @@ mod report; @@ -20,6 +20,7 @@ mod report;
mod room;
mod search;
mod session;
mod sso;
mod state;
mod sync;
mod tag;
@ -52,6 +53,7 @@ pub use report::*; @@ -52,6 +53,7 @@ pub use report::*;
pub use room::*;
pub use search::*;
pub use session::*;
pub use sso::*;
pub use state::*;
pub use sync::*;
pub use tag::*;

110
src/client_server/session.rs

@ -1,5 +1,10 @@ @@ -1,5 +1,10 @@
use std::sync::Arc;
use super::{DEVICE_ID_LENGTH, TOKEN_LENGTH};
use crate::{database::DatabaseGuard, utils, ConduitResult, Error, Ruma};
use crate::{database::DatabaseGuard, utils, ConduitResult, Database, Error, Ruma};
// use log::info;
use macaroon::Verifier;
use rocket::State;
use ruma::{
api::client::{
error::ErrorKind,
@ -8,9 +13,11 @@ use ruma::{ @@ -8,9 +13,11 @@ use ruma::{
uiaa::IncomingUserIdentifier,
},
},
events::EventType,
UserId,
};
use serde::Deserialize;
use tokio::sync::RwLock;
use tracing::info;
#[derive(Debug, Deserialize)]
@ -19,6 +26,29 @@ struct Claims { @@ -19,6 +26,29 @@ struct Claims {
exp: usize,
}
fn verifier_callback(v: &macaroon::ByteString) -> bool {
// TODO: why convert to string first, maybe ByteString has tailing zeros?
let v0 = v.to_string();
let v1 = base64::decode(v0.as_bytes()).unwrap();
if v1.starts_with(b"time < ") {
// TODO: is utf-8 needed?
let v2 = std::str::from_utf8(&v1).unwrap();
let v3 = v2.trim_start_matches("time < ");
let v4: i64 = v3.parse().unwrap();
let now = chrono::Utc::now().timestamp();
if now < v4 {
println!("OK!!");
true
} else {
println!("expired, v4={} , now={}, v4-now={}", v4, now, v4 - now);
false
}
} else {
false
}
}
#[cfg(feature = "conduit_bin")]
use rocket::{get, post};
@ -27,14 +57,21 @@ use rocket::{get, post}; @@ -27,14 +57,21 @@ use rocket::{get, post};
/// Get the supported login types of this server. One of these should be used as the `type` field
/// when logging in.
#[cfg_attr(feature = "conduit_bin", get("/_matrix/client/r0/login"))]
#[tracing::instrument]
pub async fn get_login_types_route() -> ConduitResult<get_login_types::Response> {
Ok(
get_login_types::Response::new(vec![get_login_types::LoginType::Password(
Default::default(),
)])
.into(),
)
// #[tracing::instrument] // TODO: need Debug on Database
pub async fn get_login_types_route(
db: &rocket::State<Arc<RwLock<Database>>>,
) -> ConduitResult<get_login_types::Response> {
let mut flows = vec![get_login_types::LoginType::Password(Default::default())];
let db_lock = db.read().await;
if db_lock.globals.openid_client.is_some() {
flows.push(get_login_types::LoginType::Sso(
get_login_types::SsoLoginType::default(),
));
}
Ok(get_login_types::Response { flows }.into())
}
/// # `POST /_matrix/client/r0/login`
@ -109,6 +146,61 @@ pub async fn login_route( @@ -109,6 +146,61 @@ pub async fn login_route(
UserId::parse_with_server_name(username, db.globals.server_name()).map_err(
|_| Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid."),
)?
} else if macaroon::Macaroon::deserialize(
&base64::decode_config(token, base64::URL_SAFE_NO_PAD).unwrap(),
)
.is_ok()
{
println!("TOKEN! {}", token);
let macaroon = macaroon::Macaroon::deserialize(
&base64::decode_config(token, base64::URL_SAFE_NO_PAD).unwrap(),
)
.unwrap();
let v0 = macaroon.identifier().to_string();
let v1 = base64::decode(v0.as_bytes()).unwrap();
let user_id = std::str::from_utf8(&v1).unwrap();
println!("identifier: {}", user_id);
println!("location: {:?}", macaroon.location());
println!("sig: {:?}", macaroon.signature());
let mut verifier = Verifier::default();
verifier.satisfy_general(verifier_callback);
let (key, _) = &db.globals.openid_client.as_ref().unwrap();
match verifier.verify(&macaroon, &key, Default::default()) {
Ok(()) => println!("Macaroon verified!"),
Err(error) => println!("Error validating macaroon: {:?}", error),
}
let user_id = UserId::parse_with_server_name(user_id, db.globals.server_name())
.map_err(|_| {
Error::BadRequest(ErrorKind::InvalidUsername, "Username is invalid.")
})?;
println!("user_id: {}", user_id);
if !db.users.exists(&user_id)? {
// TODO None?
db.users
.create(&user_id, Some("00000000000000000000000000000000000000000"))?; // TODO
db.account_data.update(
None,
&user_id,
EventType::PushRules,
&ruma::events::push_rules::PushRulesEvent {
content: ruma::events::push_rules::PushRulesEventContent {
global: ruma::push::Ruleset::server_default(&user_id),
},
},
&db.globals,
)?;
}
user_id
} else {
return Err(Error::BadRequest(
ErrorKind::Unknown,

188
src/client_server/sso.rs

@ -0,0 +1,188 @@ @@ -0,0 +1,188 @@
use std::sync::Arc;
// use super::State;
use crate::{server_server, ConduitResult, Database, Error, Ruma};
use http::status;
use macaroon::Macaroon;
use openid::{Token, Userinfo};
use reqwest::Url;
use rocket::{
http::{Cookie, CookieJar, Header, SameSite, Status},
response::{Redirect, Responder, Response},
};
#[cfg(feature = "conduit_bin")]
use rocket::get;
use tokio::sync::RwLock;
const MAC_VALID_SECS: i64 = 10;
#[cfg_attr(
feature = "conduit_bin",
get("/_matrix/client/r0/login/sso/redirect?<redirectUrl>")
)]
pub async fn get_sso_redirect(
db: &rocket::State<Arc<RwLock<Database>>>,
redirectUrl: &str,
mut cookies: &CookieJar<'_>,
) -> Redirect {
let db_lock = db.read().await;
let (_key, client) = db_lock.globals.openid_client.as_ref().unwrap();
let state = "value"; // TODO: random
// cookies.add_private(Cookie::new("openid-state", state));
// cookies.add_private(Cookie::new("openid-redirect-url", redirectUrl.to_string()));
let cookie1 = Cookie::build("openid-state", state)
.secure(false)
.http_only(true)
.same_site(SameSite::None)
.finish();
let cookie2 = Cookie::build("openid-redirect-url", redirectUrl.to_string())
.secure(false)
.http_only(true)
.same_site(SameSite::None)
.finish();
cookies.add_private(cookie1);
cookies.add_private(cookie2);
// https://docs.rs/openid/0.4.0/openid/struct.Options.html
let auth_url = client.auth_url(&openid::Options {
scope: Some("email".into()), // TODO: openid only?
//TODO: nonce?
state: Some(state.to_string()),
..Default::default()
});
Redirect::to(auth_url.to_string())
}
async fn request_token(
oidc_client: &openid::DiscoveredClient,
code: &str,
) -> Result<Option<(Token, Userinfo)>, Error> {
let mut token: Token = oidc_client.request_token(&code).await.unwrap().into();
if let Some(mut id_token) = token.id_token.as_mut() {
oidc_client.decode_token(&mut id_token).unwrap();
oidc_client.validate_token(&id_token, None, None).unwrap();
// eprintln!("token: {:?}", id_token);
} else {
return Ok(None);
}
let userinfo = oidc_client.request_userinfo(&token).await.unwrap();
// eprintln!("user info: {:?}", userinfo);
Ok(Some((token, userinfo)))
}
#[derive(Debug)]
struct User {
id: String,
login: Option<String>,
first_name: Option<String>,
last_name: Option<String>,
email: Option<String>,
image_url: Option<String>,
activated: bool,
lang_key: Option<String>,
authorities: Vec<String>,
}
#[derive(Debug, Responder)]
pub enum ExampleResponse<'a> {
Redirect(Redirect),
Unauthorized(rocket::response::status::Unauthorized<&'a str>),
}
#[cfg_attr(
feature = "conduit_bin",
get("/sso_return?<session_state>&<state>&<code>")
)]
// #[tracing::instrument]
pub async fn get_sso_return<'a>(
db: &rocket::State<Arc<RwLock<Database>>>,
session_state: &str,
state: &str,
code: &str,
cookies: &CookieJar<'_>,
) -> ExampleResponse<'a> {
let state_is_valid = cookies
.get_private("openid-state")
.map_or(false, |v| v.value() == state);
if !state_is_valid {
return ExampleResponse::Unauthorized(rocket::response::status::Unauthorized(Some(
"invalid state",
)));
}
let db_lock = db.read().await;
let (_key, client) = db_lock.globals.openid_client.as_ref().unwrap();
let username;
match request_token(client, code).await {
Ok(Some((_token, userinfo))) => {
/*
let id = uuid::Uuid::new_v4().to_string();
let login = userinfo.preferred_username.clone();
let email = userinfo.email.clone();
let new_user = User {
id: userinfo.sub.clone().unwrap_or_default(),
login,
last_name: userinfo.family_name.clone(),
first_name: userinfo.name.clone(),
email,
activated: userinfo.email_verified,
image_url: userinfo.picture.clone().map(|x| x.to_string()),
lang_key: Some("en".to_string()),
authorities: vec!["ROLE_USER".to_string()], //FIXME: read from token
};
*/
// user = new_user.login.unwrap();
username = userinfo.preferred_username.unwrap();
}
Ok(None) => {
return ExampleResponse::Unauthorized(rocket::response::status::Unauthorized(Some(
"no id_token found",
)));
}
Err(err) => {
eprintln!("login error in call: {:?}", err);
return ExampleResponse::Unauthorized(rocket::response::status::Unauthorized(Some(
"login error in call",
)));
}
}
let (key, _client) = db_lock.globals.openid_client.as_ref().unwrap();
// Create our macaroon
let mut macaroon = match Macaroon::create(Some("location".into()), &key, username.into()) {
Ok(macaroon) => macaroon,
Err(error) => panic!("Error creating macaroon: {:?}", error),
};
let something = format!("time < {}", chrono::Utc::now().timestamp() + MAC_VALID_SECS).into();
macaroon.add_first_party_caveat(something);
let serialized = macaroon.serialize(macaroon::Format::V2).unwrap();
let encoded = base64::encode_config(serialized, base64::URL_SAFE_NO_PAD);
let url = cookies
.get_private("openid-redirect-url")
.map(|v| {
let redirectUrl =
Url::parse_with_params(v.value(), &[("loginToken", encoded)]).unwrap();
redirectUrl
})
.unwrap();
ExampleResponse::Redirect(Redirect::to(url.to_string()))
}

14
src/database.rs

@ -18,6 +18,7 @@ use crate::{utils, Error, Result}; @@ -18,6 +18,7 @@ use crate::{utils, Error, Result};
use abstraction::DatabaseEngine;
use directories::ProjectDirs;
use lru_cache::LruCache;
use reqwest::Url;
use rocket::{
futures::{channel::mpsc, stream::FuturesUnordered, StreamExt},
outcome::{try_outcome, IntoOutcome},
@ -84,11 +85,21 @@ pub struct Config { @@ -84,11 +85,21 @@ pub struct Config {
turn_secret: String,
#[serde(default = "default_turn_ttl")]
turn_ttl: u64,
openid: Option<OpenIdConfig>,
#[serde(flatten)]
catchall: BTreeMap<String, IgnoredAny>,
}
#[derive(Clone, Debug, Deserialize)]
struct OpenIdConfig {
client_id: String,
secret: String,
redirect_url: String,
discover_url: Url,
macaroon_key: String,
}
const DEPRECATED_KEYS: &[&str] = &["cache_capacity"];
impl Config {
@ -359,7 +370,8 @@ impl Database { @@ -359,7 +370,8 @@ impl Database {
builder.open_tree("global")?,
builder.open_tree("server_signingkeys")?,
config.clone(),
)?,
)
.await?,
}));
{

26
src/database/globals.rs

@ -48,6 +48,7 @@ pub struct Globals { @@ -48,6 +48,7 @@ pub struct Globals {
pub roomid_mutex_state: RwLock<HashMap<RoomId, Arc<TokioMutex<()>>>>,
pub roomid_mutex_federation: RwLock<HashMap<RoomId, Arc<TokioMutex<()>>>>, // this lock will be held longer
pub rotate: RotationHandler,
pub openid_client: Option<(macaroon::crypto::MacaroonKey, openid::DiscoveredClient)>,
}
/// Handles "rotation" of long-polling requests. "Rotation" in this context is similar to "rotation" of log files and the like.
@ -81,7 +82,7 @@ impl Default for RotationHandler { @@ -81,7 +82,7 @@ impl Default for RotationHandler {
}
impl Globals {
pub fn load(
pub async fn load(
globals: Arc<dyn Tree>,
server_signingkeys: Arc<dyn Tree>,
config: Config,
@ -132,9 +133,29 @@ impl Globals { @@ -132,9 +133,29 @@ impl Globals {
.as_ref()
.map(|secret| jsonwebtoken::DecodingKey::from_secret(secret.as_bytes()).into_static());
let openid_client = match config.openid.as_ref() {
Some(openid) => {
let key = macaroon::MacaroonKey::from(openid.macaroon_key.as_str());
let r = (
key,
openid::DiscoveredClient::discover(
openid.client_id.to_owned(),
openid.secret.to_owned(),
Some(openid.redirect_url.to_owned()),
openid.discover_url.to_owned(),
)
.await
.unwrap(),
);
Some(r)
}
None => None,
};
let s = Self {
globals,
config,
config: config.clone(),
keypair: Arc::new(keypair),
dns_resolver: TokioAsyncResolver::tokio_from_system_conf().map_err(|_| {
Error::bad_config("Failed to set up trust dns resolver with system config.")
@ -143,6 +164,7 @@ impl Globals { @@ -143,6 +164,7 @@ impl Globals {
tls_name_override,
server_signingkeys,
jwt_decoding_key,
openid_client,
bad_event_ratelimiter: Arc::new(RwLock::new(HashMap::new())),
bad_signature_ratelimiter: Arc::new(RwLock::new(HashMap::new())),
servername_ratelimiter: Arc::new(RwLock::new(HashMap::new())),

4
src/main.rs

@ -157,6 +157,8 @@ fn setup_rocket(config: Figment, data: Arc<RwLock<Database>>) -> rocket::Rocket< @@ -157,6 +157,8 @@ fn setup_rocket(config: Figment, data: Arc<RwLock<Database>>) -> rocket::Rocket<
server_server::get_server_version_route,
server_server::get_server_keys_route,
server_server::get_server_keys_deprecated_route,
client_server::get_sso_redirect,
client_server::get_sso_return,
server_server::get_public_rooms_route,
server_server::get_public_rooms_filtered_route,
server_server::send_transaction_message_route,
@ -216,6 +218,8 @@ async fn main() { @@ -216,6 +218,8 @@ async fn main() {
let start = async {
config.warn_deprecated();
macaroon::initialize().expect("can't initialize macaroon");
let db = match Database::load_or_create(&config).await {
Ok(db) => db,
Err(e) => {

Loading…
Cancel
Save