cleaning job

This commit is contained in:
mikoto 2024-02-28 21:33:44 +00:00
parent 03d312ca68
commit d22243a357
14 changed files with 515 additions and 174 deletions

341
Cargo.lock generated
View file

@ -65,6 +65,12 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
[[package]]
name = "anyhow"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
[[package]] [[package]]
name = "arc-swap" name = "arc-swap"
version = "1.6.0" version = "1.6.0"
@ -150,6 +156,17 @@ version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f093eed78becd229346bf859eec0aa4dd7ddde0757287b2b4107a1f09c80002" checksum = "5f093eed78becd229346bf859eec0aa4dd7ddde0757287b2b4107a1f09c80002"
[[package]]
name = "async-recursion"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
]
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.77" version = "0.1.77"
@ -320,6 +337,15 @@ version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
name = "base64-url"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb9fb9fb058cc3063b5fc88d9a21eefa2735871498a04e1650da76ed511c8569"
dependencies = [
"base64 0.21.7",
]
[[package]] [[package]]
name = "base64ct" name = "base64ct"
version = "1.6.0" version = "1.6.0"
@ -462,6 +488,33 @@ dependencies = [
"windows-targets 0.52.3", "windows-targets 0.52.3",
] ]
[[package]]
name = "ciborium"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
dependencies = [
"ciborium-io",
"ciborium-ll",
"serde",
]
[[package]]
name = "ciborium-io"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
[[package]]
name = "ciborium-ll"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
dependencies = [
"ciborium-io",
"half",
]
[[package]] [[package]]
name = "clang-sys" name = "clang-sys"
version = "1.7.0" version = "1.7.0"
@ -542,6 +595,7 @@ dependencies = [
"lru-cache", "lru-cache",
"nix", "nix",
"num_cpus", "num_cpus",
"openid-client",
"openidconnect", "openidconnect",
"opentelemetry", "opentelemetry",
"opentelemetry-jaeger", "opentelemetry-jaeger",
@ -671,6 +725,12 @@ version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
[[package]]
name = "crunchy"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]] [[package]]
name = "crypto-bigint" name = "crypto-bigint"
version = "0.5.5" version = "0.5.5"
@ -927,6 +987,16 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "fallible-iterator" name = "fallible-iterator"
version = "0.2.0" version = "0.2.0"
@ -939,6 +1009,12 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]]
name = "fastrand"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]] [[package]]
name = "fdeflate" name = "fdeflate"
version = "0.3.4" version = "0.3.4"
@ -994,6 +1070,21 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 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]] [[package]]
name = "form_urlencoded" name = "form_urlencoded"
version = "1.2.1" version = "1.2.1"
@ -1178,6 +1269,16 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "half"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5eceaaeec696539ddaf7b333340f1af35a5aa87ae3e4f3ead0532f72affab2e"
dependencies = [
"cfg-if",
"crunchy",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.12.3" version = "0.12.3"
@ -1395,6 +1496,19 @@ dependencies = [
"tokio-rustls", "tokio-rustls",
] ]
[[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]] [[package]]
name = "iana-time-zone" name = "iana-time-zone"
version = "0.1.60" version = "0.1.60"
@ -1536,6 +1650,24 @@ version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "josekit"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd20997283339a19226445db97d632c8dc7adb6b8172537fe0e9e540fb141df2"
dependencies = [
"anyhow",
"base64 0.21.7",
"flate2",
"once_cell",
"openssl",
"regex",
"serde",
"serde_json",
"thiserror",
"time",
]
[[package]] [[package]]
name = "jpeg-decoder" name = "jpeg-decoder"
version = "0.3.1" version = "0.3.1"
@ -1584,6 +1716,35 @@ dependencies = [
"simple_asn1", "simple_asn1",
] ]
[[package]]
name = "jwt-compact"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25cb2458ca54de48ef237ac0d68d4e80e512ae81d6aeb9775f4c835da0d193d3"
dependencies = [
"anyhow",
"base64ct",
"chrono",
"ciborium",
"hmac",
"rand_core",
"serde",
"serde_json",
"sha2",
"smallvec",
"subtle",
"zeroize",
]
[[package]]
name = "keccak"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654"
dependencies = [
"cpufeatures",
]
[[package]] [[package]]
name = "konst" name = "konst"
version = "0.3.8" version = "0.3.8"
@ -1696,6 +1857,12 @@ version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "linux-raw-sys"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.11" version = "0.4.11"
@ -1721,6 +1888,12 @@ dependencies = [
"linked-hash-map", "linked-hash-map",
] ]
[[package]]
name = "lru_time_cache"
version = "0.11.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9106e1d747ffd48e6be5bb2d97fa706ed25b144fbee4d5c02eae110cd8d6badd"
[[package]] [[package]]
name = "lz4-sys" name = "lz4-sys"
version = "1.9.4" version = "1.9.4"
@ -1822,6 +1995,24 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "native-tls"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
dependencies = [
"lazy_static",
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
]
[[package]] [[package]]
name = "nix" name = "nix"
version = "0.26.4" version = "0.26.4"
@ -1964,6 +2155,32 @@ version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "openid-client"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca96ef162fe17a8487ed6b8ffef725c0417b2554363f6a768770de1e326e6916"
dependencies = [
"async-recursion",
"base64 0.21.7",
"base64-url",
"josekit",
"jwt-compact",
"lazy_static",
"lru_time_cache",
"querystring",
"rand",
"regex",
"reqwest",
"serde",
"serde_json",
"sha2",
"sha3",
"tokio",
"url",
"urlencoding",
]
[[package]] [[package]]
name = "openidconnect" name = "openidconnect"
version = "3.5.0" version = "3.5.0"
@ -1996,12 +2213,60 @@ dependencies = [
"url", "url",
] ]
[[package]]
name = "openssl"
version = "0.10.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f"
dependencies = [
"bitflags 2.4.2",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
]
[[package]] [[package]]
name = "openssl-probe" name = "openssl-probe"
version = "0.1.5" version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-src"
version = "300.2.3+3.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cff92b6f71555b61bb9315f7c64da3ca43d87531622120fea0195fc761b4843"
dependencies = [
"cc",
]
[[package]]
name = "openssl-sys"
version = "0.9.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff"
dependencies = [
"cc",
"libc",
"openssl-src",
"pkg-config",
"vcpkg",
]
[[package]] [[package]]
name = "opentelemetry" name = "opentelemetry"
version = "0.18.0" version = "0.18.0"
@ -2364,6 +2629,12 @@ dependencies = [
"yansi", "yansi",
] ]
[[package]]
name = "querystring"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9318ead08c799aad12a55a3e78b82e0b6167271ffd1f627b758891282f739187"
[[package]] [[package]]
name = "quick-error" name = "quick-error"
version = "1.2.3" version = "1.2.3"
@ -2489,10 +2760,12 @@ dependencies = [
"http-body 0.4.6", "http-body 0.4.6",
"hyper", "hyper",
"hyper-rustls", "hyper-rustls",
"hyper-tls",
"ipnet", "ipnet",
"js-sys", "js-sys",
"log", "log",
"mime", "mime",
"native-tls",
"once_cell", "once_cell",
"percent-encoding", "percent-encoding",
"pin-project-lite", "pin-project-lite",
@ -2505,6 +2778,7 @@ dependencies = [
"sync_wrapper", "sync_wrapper",
"system-configuration", "system-configuration",
"tokio", "tokio",
"tokio-native-tls",
"tokio-rustls", "tokio-rustls",
"tokio-socks", "tokio-socks",
"tower-service", "tower-service",
@ -2817,6 +3091,19 @@ dependencies = [
"semver", "semver",
] ]
[[package]]
name = "rustix"
version = "0.38.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
dependencies = [
"bitflags 2.4.2",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.21.10" version = "0.21.10"
@ -2995,6 +3282,7 @@ version = "1.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
dependencies = [ dependencies = [
"indexmap 2.2.3",
"itoa", "itoa",
"ryu", "ryu",
"serde", "serde",
@ -3116,6 +3404,16 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "sha3"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60"
dependencies = [
"digest",
"keccak",
]
[[package]] [[package]]
name = "sharded-slab" name = "sharded-slab"
version = "0.1.7" version = "0.1.7"
@ -3285,6 +3583,18 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "tempfile"
version = "3.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
dependencies = [
"cfg-if",
"fastrand",
"rustix",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.57" version = "1.0.57"
@ -3425,6 +3735,7 @@ dependencies = [
"libc", "libc",
"mio", "mio",
"num_cpus", "num_cpus",
"parking_lot",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
"socket2", "socket2",
@ -3443,6 +3754,16 @@ dependencies = [
"syn 2.0.51", "syn 2.0.51",
] ]
[[package]]
name = "tokio-native-tls"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
dependencies = [
"native-tls",
"tokio",
]
[[package]] [[package]]
name = "tokio-rustls" name = "tokio-rustls"
version = "0.24.1" version = "0.24.1"
@ -3810,6 +4131,12 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "urlencoding"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.7.0" version = "1.7.0"
@ -4165,6 +4492,20 @@ name = "zeroize"
version = "1.7.0" version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
dependencies = [
"zeroize_derive",
]
[[package]]
name = "zeroize_derive"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.51",
]
[[package]] [[package]]
name = "zigzag" name = "zigzag"

View file

@ -117,15 +117,14 @@ lazy_static = "1.4.0"
async-trait = "0.1.68" async-trait = "0.1.68"
sd-notify = { version = "0.4.1", optional = true } sd-notify = { version = "0.4.1", optional = true }
# Used for SSO through OIDC
openidconnect = { version = "3.5.0", features = ["jwk-alg", "accept-string-booleans"] }
url = { version = "2.5.0", features = ["serde"] } url = { version = "2.5.0", features = ["serde"] }
# Used for SSO as fallback for non-web clients # Used for SSO as fallback for non-web clients
askama = { version = "0.12.1", features = ["with-axum"] } askama = { version = "0.12.1", features = ["with-axum"] }
askama_axum = { version = "0.4.0", features = ["urlencode", "config"] } askama_axum = { version = "0.4.0", features = ["urlencode", "config"] }
time = "0.3.34" time = "0.3.34"
openid-client = "0.1.2"
openidconnect = "3.5.0"
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
nix = { version = "0.26.2", features = ["resource"] } nix = { version = "0.26.2", features = ["resource"] }
@ -176,7 +175,7 @@ systemd-units = { unit-name = "matrix-conduit" }
[profile.dev] [profile.dev]
lto = 'off' lto = 'off'
incremental = false incremental = true
[profile.release] [profile.release]
lto = 'thin' lto = 'thin'

View file

@ -58,15 +58,41 @@ address = "127.0.0.1" # This makes sure Conduit can only be reached using the re
macaroon_key = "this is the key" # Currently only used in SSO as short-term login token macaroon_key = "this is the key" # Currently only used in SSO as short-term login token
[[global.sso]]
id = "authentik"
name = "authentik"
issuer = "https://your.authentik.example.org/application/o/your-app-slug"
scopes = ["openid", "profile", "email"]
[global.sso.client]
id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
[[global.sso]]
id = "github"
name = "Github"
subject_claim = "id"
# localpart = "{{ user.login }}"
# display_name = "{{ user.name }}"
scopes = ["read:user"]
issuer = "https://github.com"
[global.sso.client]
id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
[global.sso.discover.manual]
auth = "https://github.com/login/oauth/authorize"
token = "https://github.com/login/oauth/access_token"
userinfo = "https://api.github.com/user"
[[global.sso]] [[global.sso]]
id = "gitlab" id = "gitlab"
name = "Gitlab" name = "Gitlab"
icon = "mxc://kurosaki.cx/KKbSvyoUEYXdrzXBJoOJoLpZbqFYrCpW" icon = "mxc://kurosaki.cx/KKbSvyoUEYXdrzXBJoOJoLpZbqFYrCpW"
issuer = "https://gitlab.com"
scopes = ["openid", "profile"] scopes = ["openid", "profile"]
issuer = "https://gitlab.com"
[global.sso.client] [global.sso.client]
id = "12dd00d057420beda06fd5edcd21287026dc0c66ba5c02d40c2eff8b559c6709" id = "12dd00d057420beda06fd5edcd21287026dc0c66ba5c02d40c2eff8b559c6709"
secret = "3a806573cacf5da560b8c720cf32019255908c83e31ba78d280cf08a4eb619fd" secret = "3a806573cacf5da560b8c720cf32019255908c83e31ba78d280cf08a4eb619fd"
auth_method = "post" auth_method = "client_secret_post"

View file

@ -52,7 +52,7 @@
<img src="{{ icon }}"/> <img src="{{ icon }}"/>
{% when None %} {% when None %}
{% endmatch %} {% endmatch %}
<span>{{ idp.name.as_deref().unwrap_or(idp.id) }}</span> <span>{{ idp.name }}</span>
</a> </a>
</li> </li>
{% endfor %} {% endfor %}

View file

@ -152,7 +152,7 @@
<img src="{{ icon }}"/> <img src="{{ icon }}"/>
{% when None %} {% when None %}
{% endmatch %} {% endmatch %}
Optional data from {{ idp.name.as_deref().unwrap_or(idp.id) }}</h2> Optional data from {{ idp.name }}</h2>
{% if let Some(avatar_url) = user.avatar_url %} {% if let Some(avatar_url) = user.avatar_url %}
<label class="idp-detail idp-avatar" for="idp-avatar"> <label class="idp-detail idp-avatar" for="idp-avatar">
<div class="check-row"> <div class="check-row">

View file

@ -28,7 +28,7 @@ pub async fn get_login_types_route(
.sso .sso
.inner .inner
.iter() .iter()
.map(|p| p.config.clone().into()) .map(|p| p.inner.clone())
.collect(); .collect();
Ok(get_login_types::v3::Response::new(vec![ Ok(get_login_types::v3::Response::new(vec![

View file

@ -6,10 +6,8 @@ use askama::Template;
use axum::{body::Full, response::IntoResponse}; use axum::{body::Full, response::IntoResponse};
use axum_extra::extract::cookie::{Cookie, SameSite}; use axum_extra::extract::cookie::{Cookie, SameSite};
use bytes::BytesMut; use bytes::BytesMut;
use http::{HeaderValue, StatusCode}; use http::{header::SET_COOKIE, HeaderValue, StatusCode};
use openidconnect::{ use openidconnect::{AuthorizationCode, CsrfToken, RedirectUrl};
AuthorizationCode, CsrfToken,
};
use ruma::api::{ use ruma::api::{
client::{error::ErrorKind, session}, client::{error::ErrorKind, session},
OutgoingResponse, OutgoingResponse,
@ -38,39 +36,30 @@ pub async fn get_sso_redirect_with_provider(
// State(uiaa_session): State<Option<()>>, // State(uiaa_session): State<Option<()>>,
body: Ruma<session::sso_login_with_provider::v3::Request>, body: Ruma<session::sso_login_with_provider::v3::Request>,
) -> axum::response::Response { ) -> axum::response::Response {
let redirect_url = RedirectUrl::new(body.redirect_url.clone().unwrap()).unwrap();
if services().sso.get_all().is_empty() { if services().sso.get_all().is_empty() {
return Error::BadRequest(ErrorKind::NotFound, "SSO has not been configured") return Error::BadRequest(ErrorKind::NotFound, "SSO has not been configured")
.into_response(); .into_response();
} }
if body.idp_id.is_empty() { if body.idp_id.is_empty() {
return get_sso_fallback_template(body.redirect_url.as_deref().unwrap_or_default()) return get_sso_fallback_template(redirect_url.as_str())
.into_response(); .into_response();
}; };
let location = Some(body.idp_id.clone()); let provider = match services()
.sso
let (url, nonce, cookie) = .find_one(&body.idp_id)
match services().sso.find_one(&body.idp_id).map(|provider| { {
provider.handle_redirect(body.redirect_url.unwrap()) Ok(provider) => provider,
}) {
Ok(fut) => fut.await,
Err(e) => return e.into_response(), Err(e) => return e.into_response(),
}; };
let cookie = Cookie::build("openid-state", cookie) let (url, _, cookie) = provider.handle_redirect(redirect_url).await;
.path("/_conduit/client/sso")
// .secure(false) //FIXME
.secure(true)
.http_only(true)
.same_site(SameSite::None)
.max_age(time::Duration::seconds(COOKIE_STATE_EXPIRATION_SECS))
.finish()
.to_string();
let mut res = session::sso_login_with_provider::v3::Response { let mut res = session::sso_login_with_provider::v3::Response {
location, location: Some(url.to_string()),
cookie: Some(cookie), cookie: Some(cookie.to_string()),
} }
.try_into_http_response::<BytesMut>() .try_into_http_response::<BytesMut>()
.unwrap(); .unwrap();
@ -82,8 +71,13 @@ pub async fn get_sso_redirect_with_provider(
fn get_sso_fallback_template(redirect_url: &str) -> axum::response::Response { fn get_sso_fallback_template(redirect_url: &str) -> axum::response::Response {
let server_name = services().globals.server_name().to_string(); let server_name = services().globals.server_name().to_string();
let metadata = services().sso.inner.iter().map(Into::into).collect();
let redirect_url = redirect_url.to_string(); let redirect_url = redirect_url.to_string();
let metadata = services()
.sso
.inner
.iter()
.map(|p| p.inner.clone())
.collect();
let t = templates::IdpPicker { let t = templates::IdpPicker {
server_name, server_name,
@ -146,7 +140,7 @@ pub async fn get_sso_callback(
Err(error) => return error.into_response(), Err(error) => return error.into_response(),
}; };
let provider = match services().sso.find_one(macaroon.idp_id.as_ref()) { let provider = match services().sso.find_one(&macaroon.idp_id) {
Ok(provider) => provider, Ok(provider) => provider,
Err(error) => return error.into_response(), Err(error) => return error.into_response(),
}; };
@ -155,9 +149,7 @@ pub async fn get_sso_callback(
let user_info = provider.handle_callback(code, macaroon.nonce).await; let user_info = provider.handle_callback(code, macaroon.nonce).await;
( (
axum::TypedHeader(axum::headers::Location( axum::response::AppendHeaders([(SET_COOKIE, cookie)]),
HeaderValue::from_str(clear_cookie.as_str()).unwrap(),
)),
"Hello, World!", "Hello, World!",
) )
.into_response() .into_response()

View file

@ -1,6 +1,5 @@
use openidconnect::JsonWebKeyId;
use ruma::OwnedMxcUri; use ruma::OwnedMxcUri;
use serde::Deserialize; use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
pub struct ProviderConfig { pub struct ProviderConfig {
@ -37,7 +36,7 @@ pub struct ProviderConfig {
// Should be enabled when the authorization response does not contain userinfo // Should be enabled when the authorization response does not contain userinfo
#[serde(default)] #[serde(default)]
pub userinfo_override: bool, pub force_userinfo: bool,
#[serde(default)] #[serde(default)]
pub discovery: DiscoveryConfig, pub discovery: DiscoveryConfig,
@ -48,9 +47,14 @@ pub struct ClientConfig {
pub id: String, pub id: String,
// Mandatory for the following `ClientAuthMethod`s: // Mandatory for the following `ClientAuthMethod`s:
// [`Basic`,`Post`,`SharedJwt`] // [`Basic`,`Post`,`SharedJwt`]
#[serde(default)]
pub secret: Option<String>, pub secret: Option<String>,
#[serde(default)]
pub auth_method: AuthMethod, pub auth_method: AuthMethod,
// #[serde(default)]
// pub private_jwt: Option<PrivateJwt>,
} }
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
@ -59,6 +63,7 @@ pub struct Endpoints {
pub token: Option<url::Url>, pub token: Option<url::Url>,
pub userinfo: Option<url::Url>, pub userinfo: Option<url::Url>,
pub jwk: Option<url::Url>, pub jwk: Option<url::Url>,
pub ok: AuthMethod,
} }
#[derive(Clone, Debug, Default, Deserialize)] #[derive(Clone, Debug, Default, Deserialize)]
@ -70,30 +75,32 @@ pub enum DiscoveryConfig {
Manual(Endpoints), Manual(Endpoints),
} }
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum AuthMethod { pub enum AuthMethod {
#[serde(rename = "none")]
None, None,
// Provide the client combo in the Authorization header // Provide the client combo in the Authorization header
#[default]
#[serde(rename = "client_secret_basic")]
Basic, Basic,
// Provide the client combo as in the POST request body
// Provide the client combo in the POST request body
#[serde(rename = "client_secret_post")]
Post, Post,
// Provide a JWT signed with client secret // Provide a JWT signed with client secret
#[serde(rename = "client_secret_jwt")]
SharedJwt, SharedJwt,
// Provide a JWT signed with a private key (OP needs to know the public key) // Provide a JWT signed with a private key (OP needs to know the public key)
#[serde(rename = "private_key_jwt")]
PrivateJwt, PrivateJwt,
} }
#[derive(Clone, Debug, Deserialize)] // #[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "lowercase")] // pub struct PrivateJwt {
pub enum Algorithm { // pub payload:
Rsa, // pub header: jsonwebtoken::Header,
EdDsa, // pub key: jsonwebtoken::EncodingKey,
} // }
#[derive(Clone, Debug, Deserialize)]
pub struct PrivateSigningKey {
pub kind: Algorithm,
pub path: String,
pub kid: Option<JsonWebKeyId>,
}

View file

@ -24,7 +24,7 @@ use ruma::api::{
IncomingRequest, IncomingRequest,
}; };
use tokio::signal; use tokio::signal;
use tower::{ServiceBuilder, ServiceExt}; use tower::{ServiceBuilder};
use tower_http::{ use tower_http::{
cors::{self, CorsLayer}, cors::{self, CorsLayer},
trace::TraceLayer, trace::TraceLayer,

View file

@ -160,6 +160,8 @@ impl Service {
} }
}; };
let macaroon_key = config.macaroon_key.clone();
let tls_name_override = Arc::new(RwLock::new(TlsNameMap::new())); let tls_name_override = Arc::new(RwLock::new(TlsNameMap::new()));
let jwt_decoding_key = config let jwt_decoding_key = config
@ -213,7 +215,7 @@ impl Service {
sync_receivers: RwLock::new(HashMap::new()), sync_receivers: RwLock::new(HashMap::new()),
rotate: RotationHandler::new(), rotate: RotationHandler::new(),
shutdown: AtomicBool::new(false), shutdown: AtomicBool::new(false),
macaroon_key: config.macaroon_key.clone(), macaroon_key,
}; };
fs::create_dir_all(s.get_media_folder())?; fs::create_dir_all(s.get_media_folder())?;

View file

@ -1,6 +1,7 @@
use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, Validation}; use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, Validation};
use openidconnect::{Nonce, PkceCodeVerifier, RedirectUrl, CsrfToken}; use openidconnect::{CsrfToken, Nonce, RedirectUrl};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
use crate::Error; use crate::Error;
@ -9,12 +10,21 @@ pub struct Macaroon {
pub idp_id: String, pub idp_id: String,
pub nonce: Nonce, pub nonce: Nonce,
pub csrf: CsrfToken, pub csrf: CsrfToken,
pub redirect_url: Option<RedirectUrl>, pub redirect_url: RedirectUrl,
pub pkce_verifier: Option<PkceCodeVerifier>,
pub time: i64, pub time: i64,
} }
impl Macaroon { impl Macaroon {
pub fn new(idp_id: String, nonce: Nonce, csrf: CsrfToken, redirect_url: RedirectUrl) -> Self {
Self {
idp_id,
nonce,
csrf,
redirect_url,
time: OffsetDateTime::now_utc().unix_timestamp(),
}
}
pub fn encode(&self, macaroon: &str) -> Result<String, jsonwebtoken::errors::Error> { pub fn encode(&self, macaroon: &str) -> Result<String, jsonwebtoken::errors::Error> {
jsonwebtoken::encode( jsonwebtoken::encode(
&Header::default(), &Header::default(),
@ -38,7 +48,7 @@ impl Macaroon {
Err(Error::BadRequest( Err(Error::BadRequest(
ruma::api::client::error::ErrorKind::Unauthorized, ruma::api::client::error::ErrorKind::Unauthorized,
"macaroon invalid", "macaroon encoding",
)) ))
} }
} }

View file

@ -1,21 +1,15 @@
use std::sync::Arc; use std::{collections::HashMap, sync::Arc};
mod session;
use axum_extra::extract::cookie::{Cookie, SameSite};
use futures_util::future::{self}; use futures_util::future::{self};
use openidconnect::{ use openidconnect::{
core::{ core::{CoreAuthenticationFlow, CoreClient, CoreIdTokenClaims, CoreProviderMetadata},
CoreAuthenticationFlow, CoreClient, CoreGenderClaim, CoreIdTokenClaims, reqwest::{async_http_client, http_client},
CoreProviderMetadata, CoreUserInfoClaims, AdditionalClaims, AuthUrl, AuthorizationCode, ClientId, ClientSecret, CsrfToken, EndUserName,
}, IdTokenClaims, IssuerUrl, Nonce, RedirectUrl, Scope, StandardClaims, TokenResponse, TokenUrl,
reqwest::async_http_client, UserInfoUrl,
AccessTokenHash, AdditionalClaims, AuthUrl, AuthorizationCode, ClientId, ClientSecret,
CsrfToken, IssuerUrl, Nonce, NonceVerifier, OAuth2TokenResponse, PkceCodeChallenge,
PkceCodeVerifier, RedirectUrl, Scope, SubjectIdentifier, TokenResponse, TokenUrl,
UserInfoClaims, UserInfoUrl,
}; };
use ruma::api::client::{error::ErrorKind, session::get_login_types::v3::IdentityProvider}; use ruma::api::client::{error::ErrorKind, session::get_login_types::v3::IdentityProvider};
use time::{macros::format_description, OffsetDateTime};
use crate::{ use crate::{
config::{ClientConfig, DiscoveryConfig as Discovery, ProviderConfig}, config::{ClientConfig, DiscoveryConfig as Discovery, ProviderConfig},
@ -35,9 +29,10 @@ pub struct Service {
impl Service { impl Service {
pub async fn build(config: &Config) -> Arc<Self> { pub async fn build(config: &Config) -> Arc<Self> {
Arc::new(Self { // let inner = future::join_all(config.sso.clone().into_iter().map(Provider::new)).await;
inner: future::join_all(config.sso.clone().into_iter().map(Provider::new)).await, let inner = config.sso.clone().into_iter().map(Provider::new).collect();
})
Arc::new(Self { inner })
} }
pub fn find_one(&self, idp_id: impl AsRef<str>) -> Result<Provider, Error> { pub fn find_one(&self, idp_id: impl AsRef<str>) -> Result<Provider, Error> {
@ -60,60 +55,47 @@ pub struct Provider {
pub inner: IdentityProvider, pub inner: IdentityProvider,
pub client: Arc<CoreClient>, pub client: Arc<CoreClient>,
pub scopes: Vec<String>, pub scopes: Vec<String>,
pub pkce: Option<bool>,
pub subject_claim: Option<String>, pub subject_claim: Option<String>,
} }
impl Provider { impl Provider {
pub async fn new(config: ProviderConfig) -> Self { pub fn new(config: ProviderConfig) -> Self {
let inner = IdentityProvider { Self {
client: Provider::create_client(config.discovery, config.issuer, config.client)
.unwrap(),
inner: IdentityProvider {
id: config.id.clone(), id: config.id.clone(),
name: config.name.unwrap_or(config.id), name: config.name.unwrap_or(config.id),
icon: config.icon, icon: config.icon,
brand: None, brand: None,
}; },
Self {
inner,
client: Provider::create_client(config.discovery, config.issuer, config.client)
.await
.unwrap(),
scopes: config.scopes, scopes: config.scopes,
pkce: config.pkce,
subject_claim: config.subject_claim, subject_claim: config.subject_claim,
} }
} }
async fn create_client( fn create_client(
discovery: Discovery, discovery: Discovery,
issuer: url::Url, issuer: url::Url,
config: ClientConfig, config: ClientConfig,
) -> Result<Arc<CoreClient>, Error> { ) -> Result<Arc<CoreClient>, Error> {
let mut base_url = url::Url::try_from( let base_url = services()
services()
.globals .globals
.well_known_client() .well_known_client()
.as_deref() .as_deref()
.unwrap_or(services().globals.server_name().as_str()), .unwrap_or(services().globals.server_name().as_str());
)
.expect("server_name should be a valid URL");
base_url.set_path("_conduit/config/sso/callback"); let redirect_url =
let redirect_url = RedirectUrl::from_url(base_url); RedirectUrl::new(format!("https://{base_url}/_conduit/config/sso/callback"))
.expect("server_name should be a valid URL");
let config = match discovery { let config = match discovery {
Discovery::Automatic => { Discovery::Automatic => {
let url = issuer.to_string(); let discovery = CoreProviderMetadata::discover(
let url = url.strip_suffix("/").unwrap(); &IssuerUrl::from_url(issuer),
http_client,
let discovery = CoreProviderMetadata::discover_async(
// https://github.com/ramosbugs/openidconnect-rs/issues/77
IssuerUrl::new(url.to_owned()).unwrap(),
async_http_client,
) )
.await
.unwrap(); .unwrap();
// .map_err(|e| Error::BadConfig(&e.to_string()))?;
CoreClient::from_provider_metadata( CoreClient::from_provider_metadata(
discovery, discovery,
@ -136,50 +118,41 @@ impl Provider {
Ok(Arc::new(config)) Ok(Arc::new(config))
} }
pub async fn handle_redirect(&self, redirect_url: &RedirectUrl) -> (url::Url, String, String) { pub async fn handle_redirect(&self, redirect_url: RedirectUrl) -> (url::Url, Nonce, Cookie) {
let client = self.client.clone(); let req = self
let scopes = self.scopes.iter().map(ToOwned::to_owned).map(Scope::new); .client
let mut req = client
.authorize_url( .authorize_url(
CoreAuthenticationFlow::Implicit(true), CoreAuthenticationFlow::AuthorizationCode,
|| CsrfToken::new_random_len(48), || CsrfToken::new_random_len(48),
|| Nonce::new_random_len(48), || Nonce::new_random_len(48),
) )
.add_scopes(scopes); .add_scopes(self.scopes.iter().map(ToOwned::to_owned).map(Scope::new));
let pkce_verifier = match self.pkce {
Some(true) => {
let (challenge, verifier) = PkceCodeChallenge::new_random_sha256();
req = req.set_pkce_challenge(challenge);
Some(verifier)
}
_ => None,
};
let (url, csrf, nonce) = req.url(); let (url, csrf, nonce) = req.url();
let key = services() let mac = Macaroon::new(
.globals self.inner.id.clone(),
.macaroon_key nonce.clone(),
.as_deref()
.expect("macaroon key")
.to_owned();
let cookie = Macaroon {
idp_id: self.inner.id.clone(),
csrf, csrf,
nonce: nonce.clone(), redirect_url.clone(),
time: OffsetDateTime::now_utc().unix_timestamp(), );
redirect_url: Some(redirect_url.clone()),
pkce_verifier,
};
let cookie = cookie.encode(&key).expect("bad key");
(url, nonce.secret().to_owned(), cookie) let cookie = Cookie::build(
"sso-state",
mac.encode(&services().globals.macaroon_key.as_deref().unwrap())
.expect("bad key"),
)
.path("/_conduit/client/sso")
.secure(true)
.http_only(true)
.same_site(SameSite::None)
.max_age(time::Duration::seconds(COOKIE_STATE_EXPIRATION_SECS))
.finish();
(url, nonce, cookie)
} }
pub async fn handle_callback<Claims: AdditionalClaims>( pub async fn handle_callback(
&self, &self,
code: AuthorizationCode, code: AuthorizationCode,
nonce: Nonce, nonce: Nonce,
@ -196,15 +169,22 @@ impl Provider {
.claims(&self.client.id_token_verifier(), &nonce) .claims(&self.client.id_token_verifier(), &nonce)
.unwrap(); .unwrap();
if let Some(expected) = claims.access_token_hash() { let claims_map: HashMap<String, String> = serde_json::to_string(claims)
let found = .map(|s| serde_json::from_str(&s).unwrap())
AccessTokenHash::from_token(resp.access_token(), &id_token.signing_alg().unwrap())
.unwrap(); .unwrap();
tracing::info!(?claims_map);
if &found != expected { Ok(())
panic!()
} // if let Some(expected) = claims.access_token_hash() {
} // let found =
// AccessTokenHash::from_token(resp.access_token(), &id_token.signing_alg().unwrap())
// .unwrap();
// if &found != expected {
// panic!()
// }
// }
// match self.client.user_info( // match self.client.user_info(
// resp.access_token().to_owned(), // resp.access_token().to_owned(),

View file

@ -1,6 +1,6 @@
use askama::Template; use askama::Template;
use ruma::{ use ruma::{
api::client::search::search_events::v3::UserProfile, OwnedMxcUri, OwnedServerName, OwnedUserId, api::client::{search::search_events::v3::UserProfile, session::get_login_types::v3::IdentityProvider}, OwnedMxcUri, OwnedServerName, OwnedUserId,
}; };
use super::Provider; use super::Provider;
@ -13,22 +13,6 @@ pub struct AuthConfirmation {
idp_name: String, idp_name: String,
} }
pub struct Metadata {
id: String,
name: Option<String>,
icon: Option<OwnedMxcUri>,
}
impl From<&Provider> for Metadata {
fn from(value: &Provider) -> Self {
Self {
id: value.config.id.clone(),
name: value.config.name.clone(),
icon: value.config.icon.clone(),
}
}
}
#[derive(Template)] #[derive(Template)]
#[template(path = "auth_failure.html", escape = "none")] #[template(path = "auth_failure.html", escape = "none")]
pub struct AuthFailure { pub struct AuthFailure {
@ -46,7 +30,7 @@ pub struct Deactivated {}
#[template(path = "idp_picker.html", escape = "none")] #[template(path = "idp_picker.html", escape = "none")]
pub struct IdpPicker { pub struct IdpPicker {
pub server_name: String, pub server_name: String,
pub metadata: Vec<Metadata>, pub metadata: Vec<IdentityProvider>,
pub redirect_url: String, pub redirect_url: String,
} }
@ -54,7 +38,7 @@ pub struct IdpPicker {
#[template(path = "registration.html", escape = "none")] #[template(path = "registration.html", escape = "none")]
pub struct Registration { pub struct Registration {
pub server_name: OwnedServerName, pub server_name: OwnedServerName,
pub idp: Metadata, pub idp: IdentityProvider,
pub user: Attributes, pub user: Attributes,
} }

View file

@ -5,7 +5,7 @@ use cmp::Ordering;
use rand::prelude::*; use rand::prelude::*;
use ring::digest; use ring::digest;
use ruma::{ use ruma::{
canonical_json::try_from_json_map, CanonicalJsonError, CanonicalJsonObject, MxcUri, MxcUriError, canonical_json::try_from_json_map, CanonicalJsonError, CanonicalJsonObject, MxcUri, MxcUriError, OwnedMxcUri,
}; };
use std::{ use std::{
cmp, fmt, cmp, fmt,