mirror of
https://github.com/kanidm/kanidm.git
synced 2025-05-23 17:33:57 +02:00
Update to the latest compact-jwt version (#2331)
This commit is contained in:
parent
916bb4ec04
commit
ac299b5286
134
Cargo.lock
generated
134
Cargo.lock
generated
|
@ -212,9 +212,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "async-compression"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f658e2baef915ba0f26f1f7c42bfb8e12f532a01f449a090ded75ae7a07e9ba2"
|
||||
checksum = "bc2d0cfb2a7388d34f590e76686704c494ed7aaceed62ee1ba35cbf363abc2a5"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"futures-core",
|
||||
|
@ -578,9 +578,9 @@ checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9"
|
|||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.7.0"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019"
|
||||
checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"regex-automata 0.4.3",
|
||||
|
@ -806,6 +806,24 @@ dependencies = [
|
|||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compact_jwt"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75968a6d3a1232f93c8701152281fba5ae2f936091f97fe746e35bd8a892f9d0"
|
||||
dependencies = [
|
||||
"base64 0.21.5",
|
||||
"base64urlsafedata",
|
||||
"hex",
|
||||
"kanidm-hsm-crypto",
|
||||
"openssl",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tracing",
|
||||
"url",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "concread"
|
||||
version = "0.4.3"
|
||||
|
@ -1216,9 +1234,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.4.0"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
|
||||
checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
|
||||
|
||||
[[package]]
|
||||
name = "der-parser"
|
||||
|
@ -1415,18 +1433,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "enum-map"
|
||||
version = "2.7.1"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed40247825a1a0393b91b51d475ea1063a6cbbf0847592e7f13fb427aca6a716"
|
||||
checksum = "09e6b4f374c071b18172e23134e01026653dc980636ee139e0dfe59c538c61e5"
|
||||
dependencies = [
|
||||
"enum-map-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum-map-derive"
|
||||
version = "0.15.0"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7933cd46e720348d29ed1493f89df9792563f272f96d8f13d18afe03b32f8cb8"
|
||||
checksum = "bfdb3d73d1beaf47c8593a1364e577fde072677cbfd103600345c0f547408cc0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1482,9 +1500,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
|||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.6"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e"
|
||||
checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
|
@ -1649,9 +1667,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
|||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.2.0"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
|
||||
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
@ -2503,9 +2521,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.21"
|
||||
version = "0.3.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833"
|
||||
checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
|
@ -2513,7 +2531,7 @@ dependencies = [
|
|||
"futures-sink",
|
||||
"futures-util",
|
||||
"http",
|
||||
"indexmap 1.9.3",
|
||||
"indexmap 2.1.0",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
|
@ -2773,9 +2791,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
|
||||
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
|
||||
dependencies = [
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
|
@ -2976,9 +2994,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "kanidm-hsm-crypto"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2710fd18cfe2f774e6d1e743dae86ae9a7332cad1bb85cb66777f7ef63578410"
|
||||
checksum = "fdc2a5dbe42b03b3e5e3f99eab1c5773032c8e508896691b3f4562c7de264d67"
|
||||
dependencies = [
|
||||
"argon2",
|
||||
"openssl",
|
||||
|
@ -3122,7 +3140,7 @@ dependencies = [
|
|||
"async-recursion",
|
||||
"clap",
|
||||
"clap_complete",
|
||||
"compact_jwt",
|
||||
"compact_jwt 0.3.2",
|
||||
"cursive",
|
||||
"dialoguer",
|
||||
"futures-concurrency",
|
||||
|
@ -3206,7 +3224,7 @@ dependencies = [
|
|||
"axum-server",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"compact_jwt",
|
||||
"compact_jwt 0.3.2",
|
||||
"cron",
|
||||
"filetime",
|
||||
"futures",
|
||||
|
@ -3253,7 +3271,7 @@ version = "1.1.0-rc.15-dev"
|
|||
dependencies = [
|
||||
"base64 0.21.5",
|
||||
"base64urlsafedata",
|
||||
"compact_jwt",
|
||||
"compact_jwt 0.3.2",
|
||||
"concread",
|
||||
"criterion",
|
||||
"dyn-clone",
|
||||
|
@ -3319,7 +3337,7 @@ name = "kanidmd_testkit"
|
|||
version = "1.1.0-rc.15-dev"
|
||||
dependencies = [
|
||||
"assert_cmd",
|
||||
"compact_jwt",
|
||||
"compact_jwt 0.3.2",
|
||||
"escargot",
|
||||
"fantoccini",
|
||||
"futures",
|
||||
|
@ -3604,9 +3622,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lodepng"
|
||||
version = "3.9.1"
|
||||
version = "3.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3cdccd0cf57a5d456f0656ebcff72c2e19503287e1afbf3b84382812adc0606"
|
||||
checksum = "b00f56ff9bcd5721ab172b73eac8a7d4e9439f47a98581e666178dbe7df97e13"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"fallible_collections",
|
||||
|
@ -4085,9 +4103,9 @@ checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
|||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.59"
|
||||
version = "0.10.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33"
|
||||
checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"cfg-if",
|
||||
|
@ -4117,9 +4135,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
|||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.95"
|
||||
version = "0.9.96"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9"
|
||||
checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
|
@ -4413,9 +4431,9 @@ checksum = "36bae92c60fa2398ce4678b98b2c4b5a7c61099961ca1fa305aec04a9ad28922"
|
|||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.0"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
|
@ -4967,12 +4985,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rtoolbox"
|
||||
version = "0.0.1"
|
||||
version = "0.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "034e22c514f5c0cb8a10ff341b9b048b5ceb21591f31c8f44c43b960f9b3524a"
|
||||
checksum = "c247d24e63230cdb56463ae328478bd5eac8b8faa8c69461a77e8e323afac90e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -5062,9 +5080,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.21"
|
||||
version = "0.38.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"
|
||||
checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"errno",
|
||||
|
@ -5207,9 +5225,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.192"
|
||||
version = "1.0.193"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001"
|
||||
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
@ -5267,9 +5285,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.192"
|
||||
version = "1.0.193"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1"
|
||||
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -5467,9 +5485,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.11.1"
|
||||
version = "1.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
|
||||
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
@ -6170,9 +6188,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
|
|||
|
||||
[[package]]
|
||||
name = "unicode-bom"
|
||||
version = "2.0.2"
|
||||
version = "2.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98e90c70c9f0d4d1ee6d0a7d04aa06cb9bbd53d8cfbdd62a0269a7c2eb640552"
|
||||
checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
|
@ -6209,12 +6227,12 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
|||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.4.1"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
|
||||
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna 0.4.0",
|
||||
"idna 0.5.0",
|
||||
"percent-encoding",
|
||||
"serde",
|
||||
]
|
||||
|
@ -6276,9 +6294,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.5.0"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc"
|
||||
checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"serde",
|
||||
|
@ -6518,7 +6536,7 @@ source = "git+https://github.com/kanidm/webauthn-rs.git?rev=2218d2055c0c900ef57b
|
|||
dependencies = [
|
||||
"base64 0.21.5",
|
||||
"base64urlsafedata",
|
||||
"compact_jwt",
|
||||
"compact_jwt 0.2.10",
|
||||
"der-parser",
|
||||
"nom",
|
||||
"openssl",
|
||||
|
@ -6949,18 +6967,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.25"
|
||||
version = "0.7.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557"
|
||||
checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.25"
|
||||
version = "0.7.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b"
|
||||
checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -6969,9 +6987,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.6.0"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
|
||||
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
|
||||
dependencies = [
|
||||
"zeroize_derive",
|
||||
]
|
||||
|
|
|
@ -115,7 +115,7 @@ clap = { version = "^4.4.8", features = ["derive", "env"] }
|
|||
clap_complete = "^4.4.4"
|
||||
# Forced by saffron/cron
|
||||
chrono = "^0.4.31"
|
||||
compact_jwt = { version = "^0.2.10", default-features = false }
|
||||
compact_jwt = { version = "^0.3.2", default-features = false }
|
||||
concread = "^0.4.3"
|
||||
cron = "0.12.0"
|
||||
crossbeam = "0.8.1"
|
||||
|
|
|
@ -25,7 +25,7 @@ use axum::routing::*;
|
|||
use axum::Router;
|
||||
use axum_csp::{CspDirectiveType, CspValue};
|
||||
use axum_macros::FromRef;
|
||||
use compact_jwt::{Jws, JwsSigner, JwsUnverified};
|
||||
use compact_jwt::{JwsCompact, JwsHs256Signer, JwsVerifier};
|
||||
use hashbrown::HashMap;
|
||||
use http::{HeaderMap, HeaderValue};
|
||||
use hyper::server::accept::Accept;
|
||||
|
@ -59,8 +59,7 @@ pub struct ServerState {
|
|||
pub qe_w_ref: &'static crate::actors::v1_write::QueryServerWriteV1,
|
||||
pub qe_r_ref: &'static crate::actors::v1_read::QueryServerReadV1,
|
||||
// Store the token management parts.
|
||||
pub jws_signer: compact_jwt::JwsSigner,
|
||||
pub jws_validator: compact_jwt::JwsValidator,
|
||||
pub jws_signer: compact_jwt::JwsHs256Signer,
|
||||
// The SHA384 hashes of javascript files we're going to serve to users
|
||||
pub js_files: JavaScriptFiles,
|
||||
pub(crate) trust_x_forward_for: bool,
|
||||
|
@ -69,11 +68,13 @@ pub struct ServerState {
|
|||
|
||||
impl ServerState {
|
||||
fn reinflate_uuid_from_bytes(&self, input: &str) -> Option<Uuid> {
|
||||
match JwsUnverified::from_str(input) {
|
||||
Ok(val) => val
|
||||
.validate(&self.jws_validator)
|
||||
.map(|jws: Jws<SessionId>| jws.into_inner().sessionid)
|
||||
.ok(),
|
||||
match JwsCompact::from_str(input) {
|
||||
Ok(val) => self
|
||||
.jws_signer
|
||||
.verify(&val)
|
||||
.ok()
|
||||
.and_then(|jws| jws.from_json::<SessionId>().ok())
|
||||
.map(|inner| inner.sessionid),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
@ -168,16 +169,12 @@ pub fn get_js_files(role: ServerRole) -> Result<JavaScriptFiles, ()> {
|
|||
|
||||
pub async fn create_https_server(
|
||||
config: Configuration,
|
||||
jws_signer: JwsSigner,
|
||||
jws_signer: JwsHs256Signer,
|
||||
status_ref: &'static StatusActor,
|
||||
qe_w_ref: &'static QueryServerWriteV1,
|
||||
qe_r_ref: &'static QueryServerReadV1,
|
||||
mut rx: broadcast::Receiver<CoreAction>,
|
||||
) -> Result<tokio::task::JoinHandle<()>, ()> {
|
||||
let jws_validator = jws_signer.get_validator().map_err(|e| {
|
||||
error!(?e, "Failed to get jws validator");
|
||||
})?;
|
||||
|
||||
let js_files = get_js_files(config.role)?;
|
||||
// set up the CSP headers
|
||||
// script-src 'self'
|
||||
|
@ -229,7 +226,6 @@ pub async fn create_https_server(
|
|||
qe_w_ref,
|
||||
qe_r_ref,
|
||||
jws_signer,
|
||||
jws_validator,
|
||||
js_files,
|
||||
trust_x_forward_for,
|
||||
csp_header: csp_header.finish(),
|
||||
|
|
|
@ -5,7 +5,7 @@ use axum::middleware::from_fn;
|
|||
use axum::response::{IntoResponse, Response};
|
||||
use axum::routing::{delete, get, post, put};
|
||||
use axum::{Extension, Json, Router};
|
||||
use compact_jwt::Jws;
|
||||
use compact_jwt::{Jws, JwsSigner};
|
||||
use http::{HeaderMap, HeaderValue};
|
||||
use kanidm_proto::constants::uri::V1_AUTH_VALID;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -2571,9 +2571,13 @@ fn auth_session_state_management(
|
|||
debug!("🧩 -> AuthState::Choose"); // TODO: this should be ... less work
|
||||
// Ensure the auth-session-id is set
|
||||
let kref = &state.jws_signer;
|
||||
let jws = Jws::new(SessionId { sessionid });
|
||||
let jws = Jws::into_json(&SessionId { sessionid }).map_err(|e| {
|
||||
error!(?e);
|
||||
OperationError::InvalidSessionState
|
||||
})?;
|
||||
|
||||
// Get the header token ready.
|
||||
jws.sign(kref)
|
||||
kref.sign(&jws)
|
||||
.map(|jwss| {
|
||||
auth_session_id_tok = Some(jwss.to_string());
|
||||
})
|
||||
|
@ -2587,8 +2591,11 @@ fn auth_session_state_management(
|
|||
debug!("🧩 -> AuthState::Continue");
|
||||
let kref = &state.jws_signer;
|
||||
// Get the header token ready.
|
||||
let jws = Jws::new(SessionId { sessionid });
|
||||
jws.sign(kref)
|
||||
let jws = Jws::into_json(&SessionId { sessionid }).map_err(|e| {
|
||||
error!(?e);
|
||||
OperationError::InvalidSessionState
|
||||
})?;
|
||||
kref.sign(&jws)
|
||||
.map(|jwss| {
|
||||
auth_session_id_tok = Some(jwss.to_string());
|
||||
})
|
||||
|
|
|
@ -40,7 +40,7 @@ use std::path::Path;
|
|||
use std::sync::Arc;
|
||||
|
||||
use crate::utils::touch_file_or_quit;
|
||||
use compact_jwt::JwsSigner;
|
||||
use compact_jwt::JwsHs256Signer;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use kanidmd_lib::be::{Backend, BackendConfig, BackendTransaction};
|
||||
use kanidmd_lib::idm::ldap::LdapServer;
|
||||
|
@ -853,7 +853,7 @@ pub async fn create_server_core(
|
|||
|
||||
// Extract any configuration from the IDMS that we may need.
|
||||
// For now we just do this per run, but we need to extract this from the db later.
|
||||
let jws_signer = match JwsSigner::generate_hs256() {
|
||||
let jws_signer = match JwsHs256Signer::generate_hs256() {
|
||||
Ok(k) => k,
|
||||
Err(e) => {
|
||||
error!("Unable to setup jws signer -> {:?}", e);
|
||||
|
|
|
@ -28,7 +28,7 @@ harness = false
|
|||
[dependencies]
|
||||
base64 = { workspace = true }
|
||||
base64urlsafedata = { workspace = true }
|
||||
compact_jwt = { workspace = true, features = ["openssl"] }
|
||||
compact_jwt = { workspace = true, features = ["openssl", "hsm-crypto"] }
|
||||
concread = { workspace = true }
|
||||
dyn-clone = { workspace = true }
|
||||
enum-iterator = { workspace = true }
|
||||
|
|
|
@ -29,7 +29,7 @@ pub use std::collections::BTreeSet as Set;
|
|||
use std::collections::{BTreeMap as Map, BTreeMap, BTreeSet};
|
||||
use std::sync::Arc;
|
||||
|
||||
use compact_jwt::JwsSigner;
|
||||
use compact_jwt::JwsEs256Signer;
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use kanidm_proto::internal::ImageValue;
|
||||
use kanidm_proto::v1::{
|
||||
|
@ -2834,7 +2834,7 @@ impl<VALID, STATE> Entry<VALID, STATE> {
|
|||
.and_then(|vs| vs.to_private_binary_single())
|
||||
}
|
||||
|
||||
pub fn get_ava_single_jws_key_es256(&self, attr: Attribute) -> Option<&JwsSigner> {
|
||||
pub fn get_ava_single_jws_key_es256(&self, attr: Attribute) -> Option<&JwsEs256Signer> {
|
||||
self.attrs
|
||||
.get(attr.as_ref())
|
||||
.and_then(|vs| vs.to_jws_key_es256_single())
|
||||
|
|
|
@ -7,13 +7,11 @@ use std::convert::TryFrom;
|
|||
use std::fmt;
|
||||
use std::time::Duration;
|
||||
|
||||
// use webauthn_rs::proto::Credential as WebauthnCredential;
|
||||
use compact_jwt::{Jws, JwsSigner};
|
||||
use compact_jwt::{Jws, JwsEs256Signer, JwsSigner};
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::{
|
||||
AuthAllowed, AuthCredential, AuthIssueSession, AuthMech, OperationError, UserAuthToken,
|
||||
};
|
||||
// use crossbeam::channel::Sender;
|
||||
use nonempty::{nonempty, NonEmpty};
|
||||
use tokio::sync::mpsc::UnboundedSender as Sender;
|
||||
use uuid::Uuid;
|
||||
|
@ -1014,7 +1012,7 @@ impl AuthSession {
|
|||
async_tx: &Sender<DelayedAction>,
|
||||
audit_tx: &Sender<AuditEvent>,
|
||||
webauthn: &Webauthn,
|
||||
uat_jwt_signer: &JwsSigner,
|
||||
uat_jwt_signer: &JwsEs256Signer,
|
||||
pw_badlist: &HashSet<String>,
|
||||
) -> Result<AuthState, OperationError> {
|
||||
let (next_state, response) = match &mut self.state {
|
||||
|
@ -1042,14 +1040,18 @@ impl AuthSession {
|
|||
self.account_policy.authsession_expiry(),
|
||||
self.account_policy.privilege_expiry(),
|
||||
)?;
|
||||
let jwt = Jws::new(uat);
|
||||
|
||||
let jwt = Jws::into_json(&uat).map_err(|e| {
|
||||
admin_error!(?e, "Failed to serialise into Jws");
|
||||
OperationError::InvalidState
|
||||
})?;
|
||||
|
||||
// Now encrypt and prepare the token for return to the client.
|
||||
let token = jwt
|
||||
let token = uat_jwt_signer
|
||||
// Do we want to embed this? Or just give the URL? I think we embed
|
||||
// as we only need the client to be able to check it's not tampered, but
|
||||
// this isn't a root of trust.
|
||||
.sign_embed_public_jwk(uat_jwt_signer)
|
||||
.sign(&jwt)
|
||||
.map(|jwts| jwts.to_string())
|
||||
.map_err(|e| {
|
||||
admin_error!(?e, "Failed to sign UserAuthToken to Jwt");
|
||||
|
@ -1239,7 +1241,7 @@ mod tests {
|
|||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use compact_jwt::{Jws, JwsSigner, JwsUnverified};
|
||||
use compact_jwt::{JwsCompact, JwsEs256Signer, JwsEs256Verifier, JwsVerifier};
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::{
|
||||
AuthAllowed, AuthCredential, AuthIssueSession, AuthMech, UatPurpose, UserAuthToken,
|
||||
|
@ -1278,8 +1280,10 @@ mod tests {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
fn create_jwt_signer() -> JwsSigner {
|
||||
JwsSigner::generate_es256().expect("failed to construct signer.")
|
||||
fn create_jwt_signer() -> JwsEs256Signer {
|
||||
JwsEs256Signer::generate_es256()
|
||||
.expect("failed to construct signer.")
|
||||
.set_sign_option_embed_jwk(true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1411,10 +1415,16 @@ mod tests {
|
|||
&pw_badlist_cache,
|
||||
) {
|
||||
Ok(AuthState::Success(jwt, AuthIssueSession::Token)) => {
|
||||
let uat = JwsUnverified::from_str(&jwt).expect("Failed to parse jwt");
|
||||
let uat: Jws<UserAuthToken> =
|
||||
uat.validate_embeded().expect("Embedded uat not found");
|
||||
uat.into_inner()
|
||||
let jwsc = JwsCompact::from_str(&jwt).expect("Failed to parse jwt");
|
||||
|
||||
let jws_verifier =
|
||||
JwsEs256Verifier::try_from(jwsc.get_jwk_pubkey().unwrap()).unwrap();
|
||||
|
||||
jws_verifier
|
||||
.verify(&jwsc)
|
||||
.unwrap()
|
||||
.from_json::<UserAuthToken>()
|
||||
.unwrap()
|
||||
}
|
||||
_ => panic!(),
|
||||
};
|
||||
|
|
|
@ -616,7 +616,7 @@ mod tests {
|
|||
use crate::prelude::*;
|
||||
use std::str::FromStr;
|
||||
|
||||
use compact_jwt::{Jws, JwsUnverified};
|
||||
use compact_jwt::{JwsCompact, JwsEs256Verifier, JwsVerifier};
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::v1::ApiToken;
|
||||
use ldap3_proto::proto::{LdapFilter, LdapOp, LdapSearchScope, LdapSubstringFilter};
|
||||
|
@ -1119,13 +1119,16 @@ mod tests {
|
|||
|
||||
// Inspect the token to get its uuid out.
|
||||
let apitoken_unverified =
|
||||
JwsUnverified::from_str(&apitoken).expect("Failed to parse apitoken");
|
||||
JwsCompact::from_str(&apitoken).expect("Failed to parse apitoken");
|
||||
|
||||
let apitoken_inner: Jws<ApiToken> = apitoken_unverified
|
||||
.validate_embeded()
|
||||
.expect("Embedded jwk not found");
|
||||
let jws_verifier =
|
||||
JwsEs256Verifier::try_from(apitoken_unverified.get_jwk_pubkey().unwrap()).unwrap();
|
||||
|
||||
let apitoken_inner = apitoken_inner.into_inner();
|
||||
let apitoken_inner = jws_verifier
|
||||
.verify(&apitoken_unverified)
|
||||
.unwrap()
|
||||
.from_json::<ApiToken>()
|
||||
.unwrap();
|
||||
|
||||
// Bind using the token as a DN
|
||||
let sa_lbt = ldaps
|
||||
|
|
|
@ -13,8 +13,8 @@ use std::time::Duration;
|
|||
use base64::{engine::general_purpose, Engine as _};
|
||||
|
||||
use base64urlsafedata::Base64UrlSafeData;
|
||||
pub use compact_jwt::{JwkKeySet, OidcToken};
|
||||
use compact_jwt::{JwsSigner, OidcClaims, OidcSubject};
|
||||
pub use compact_jwt::{compact::JwkKeySet, OidcToken};
|
||||
use compact_jwt::{crypto::JwsRs256Signer, JwsEs256Signer, JwsSigner, OidcClaims, OidcSubject};
|
||||
use concread::cowcell::*;
|
||||
use fernet::Fernet;
|
||||
use hashbrown::HashMap;
|
||||
|
@ -216,6 +216,12 @@ impl std::fmt::Debug for OauthRSType {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Oauth2JwsSigner {
|
||||
ES256 { signer: JwsEs256Signer },
|
||||
RS256 { signer: JwsRs256Signer },
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Oauth2RS {
|
||||
name: String,
|
||||
|
@ -227,8 +233,9 @@ pub struct Oauth2RS {
|
|||
sup_scope_maps: BTreeMap<Uuid, BTreeSet<String>>,
|
||||
// Our internal exchange encryption material for this rs.
|
||||
token_fernet: Fernet,
|
||||
jws_signer: JwsSigner,
|
||||
// jws_validator: JwsValidator,
|
||||
|
||||
jws_signer: Oauth2JwsSigner,
|
||||
|
||||
// For oidc we also need our issuer url.
|
||||
iss: Url,
|
||||
// For discovery we need to build and keep a number of values.
|
||||
|
@ -398,7 +405,9 @@ impl<'a> Oauth2ResourceServersWriteTransaction<'a> {
|
|||
.get_ava_single_private_binary(Attribute::Rs256PrivateKeyDer)
|
||||
.ok_or(OperationError::InvalidValueState)
|
||||
.and_then(|key_der| {
|
||||
JwsSigner::from_rs256_der(key_der).map_err(|e| {
|
||||
JwsRs256Signer::from_rs256_der(key_der)
|
||||
.map(|signer| Oauth2JwsSigner::RS256 { signer })
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Unable to load Legacy RS256 JwsSigner from DER");
|
||||
OperationError::CryptographyError
|
||||
})
|
||||
|
@ -409,7 +418,9 @@ impl<'a> Oauth2ResourceServersWriteTransaction<'a> {
|
|||
.get_ava_single_private_binary(Attribute::Es256PrivateKeyDer)
|
||||
.ok_or(OperationError::InvalidValueState)
|
||||
.and_then(|key_der| {
|
||||
JwsSigner::from_es256_der(key_der).map_err(|e| {
|
||||
JwsEs256Signer::from_es256_der(key_der)
|
||||
.map(|signer| Oauth2JwsSigner::ES256 { signer })
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Unable to load ES256 JwsSigner from DER");
|
||||
OperationError::CryptographyError
|
||||
})
|
||||
|
@ -1081,14 +1092,16 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
|
||||
trace!(?oidc);
|
||||
|
||||
Some(
|
||||
oidc.sign(&o2rs.jws_signer)
|
||||
.map(|jwt_signed| jwt_signed.to_string())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Unable to encode uat data");
|
||||
Oauth2Error::ServerError(OperationError::InvalidState)
|
||||
})?,
|
||||
)
|
||||
let jwt_signed = match &o2rs.jws_signer {
|
||||
Oauth2JwsSigner::ES256 { signer } => signer.sign(&oidc),
|
||||
Oauth2JwsSigner::RS256 { signer } => signer.sign(&oidc),
|
||||
}
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Unable to encode uat data");
|
||||
Oauth2Error::ServerError(OperationError::InvalidState)
|
||||
})?;
|
||||
|
||||
Some(jwt_signed.to_string())
|
||||
} else {
|
||||
// id_token is not required in non-openid flows.
|
||||
None
|
||||
|
@ -1820,12 +1833,8 @@ impl<'a> IdmServerProxyReadTransaction<'a> {
|
|||
let subject_types_supported = vec![SubjectType::Public];
|
||||
|
||||
let id_token_signing_alg_values_supported = match &o2rs.jws_signer {
|
||||
JwsSigner::ES256 { .. } => vec![IdTokenSignAlg::ES256],
|
||||
JwsSigner::RS256 { .. } => vec![IdTokenSignAlg::RS256],
|
||||
JwsSigner::HS256 { .. } => {
|
||||
admin_warn!("Invalid OAuth2 configuration - HS256 is not supported!");
|
||||
vec![]
|
||||
}
|
||||
Oauth2JwsSigner::ES256 { .. } => vec![IdTokenSignAlg::ES256],
|
||||
Oauth2JwsSigner::RS256 { .. } => vec![IdTokenSignAlg::RS256],
|
||||
};
|
||||
|
||||
let userinfo_signing_alg_values_supported = None;
|
||||
|
@ -1888,13 +1897,15 @@ impl<'a> IdmServerProxyReadTransaction<'a> {
|
|||
OperationError::NoMatchingEntries
|
||||
})?;
|
||||
|
||||
o2rs.jws_signer
|
||||
.public_key_as_jwk()
|
||||
.map_err(|e| {
|
||||
admin_error!("Unable to retrieve public key for {} - {:?}", o2rs.name, e);
|
||||
OperationError::InvalidState
|
||||
})
|
||||
.map(|jwk| JwkKeySet { keys: vec![jwk] })
|
||||
match &o2rs.jws_signer {
|
||||
Oauth2JwsSigner::ES256 { signer } => signer.public_key_as_jwk(),
|
||||
Oauth2JwsSigner::RS256 { signer } => signer.public_key_as_jwk(),
|
||||
}
|
||||
.map_err(|e| {
|
||||
admin_error!("Unable to retrieve public key for {} - {:?}", o2rs.name, e);
|
||||
OperationError::InvalidState
|
||||
})
|
||||
.map(|jwk| JwkKeySet { keys: vec![jwk] })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1997,7 +2008,10 @@ mod tests {
|
|||
use std::time::Duration;
|
||||
|
||||
use base64urlsafedata::Base64UrlSafeData;
|
||||
use compact_jwt::{JwaAlg, Jwk, JwkUse, JwsValidator, OidcSubject, OidcUnverified};
|
||||
use compact_jwt::{
|
||||
compact::JwkUse, crypto::JwsRs256Verifier, JwaAlg, Jwk, JwsEs256Verifier, JwsVerifier,
|
||||
OidcSubject, OidcUnverified,
|
||||
};
|
||||
use kanidm_proto::constants::*;
|
||||
use kanidm_proto::oauth2::*;
|
||||
use kanidm_proto::v1::UserAuthToken;
|
||||
|
@ -3581,15 +3595,18 @@ mod tests {
|
|||
|
||||
let public_jwk = jwkset.keys.pop().expect("no such jwk");
|
||||
|
||||
let jws_validator = JwsValidator::try_from(&public_jwk).expect("failed to build validator");
|
||||
let jws_validator =
|
||||
JwsEs256Verifier::try_from(&public_jwk).expect("failed to build validator");
|
||||
|
||||
let oidc_unverified =
|
||||
OidcUnverified::from_str(&id_token).expect("Failed to parse id_token");
|
||||
|
||||
let iat = ct.as_secs() as i64;
|
||||
|
||||
let oidc = oidc_unverified
|
||||
.validate(&jws_validator, iat)
|
||||
let oidc = jws_validator
|
||||
.verify(&oidc_unverified)
|
||||
.unwrap()
|
||||
.verify_exp(iat)
|
||||
.expect("Failed to verify oidc");
|
||||
|
||||
// Are the id_token values what we expect?
|
||||
|
@ -3750,15 +3767,18 @@ mod tests {
|
|||
.expect("Failed to get public key");
|
||||
let public_jwk = jwkset.keys.pop().expect("no such jwk");
|
||||
|
||||
let jws_validator = JwsValidator::try_from(&public_jwk).expect("failed to build validator");
|
||||
let jws_validator =
|
||||
JwsEs256Verifier::try_from(&public_jwk).expect("failed to build validator");
|
||||
|
||||
let oidc_unverified =
|
||||
OidcUnverified::from_str(&id_token).expect("Failed to parse id_token");
|
||||
|
||||
let iat = ct.as_secs() as i64;
|
||||
|
||||
let oidc = oidc_unverified
|
||||
.validate(&jws_validator, iat)
|
||||
let oidc = jws_validator
|
||||
.verify(&oidc_unverified)
|
||||
.unwrap()
|
||||
.verify_exp(iat)
|
||||
.expect("Failed to verify oidc");
|
||||
|
||||
// Do we have the short username in the token claims?
|
||||
|
@ -3836,15 +3856,18 @@ mod tests {
|
|||
.expect("Failed to get public key");
|
||||
let public_jwk = jwkset.keys.pop().expect("no such jwk");
|
||||
|
||||
let jws_validator = JwsValidator::try_from(&public_jwk).expect("failed to build validator");
|
||||
let jws_validator =
|
||||
JwsEs256Verifier::try_from(&public_jwk).expect("failed to build validator");
|
||||
|
||||
let oidc_unverified =
|
||||
OidcUnverified::from_str(&id_token).expect("Failed to parse id_token");
|
||||
|
||||
let iat = ct.as_secs() as i64;
|
||||
|
||||
let oidc = oidc_unverified
|
||||
.validate(&jws_validator, iat)
|
||||
let oidc = jws_validator
|
||||
.verify(&oidc_unverified)
|
||||
.unwrap()
|
||||
.verify_exp(iat)
|
||||
.expect("Failed to verify oidc");
|
||||
|
||||
// does our id_token contain the expected groups?
|
||||
|
@ -3993,15 +4016,18 @@ mod tests {
|
|||
assert!(token_response.token_type == "bearer");
|
||||
let id_token = token_response.id_token.expect("No id_token in response!");
|
||||
|
||||
let jws_validator = JwsValidator::try_from(&public_jwk).expect("failed to build validator");
|
||||
let jws_validator =
|
||||
JwsRs256Verifier::try_from(&public_jwk).expect("failed to build validator");
|
||||
|
||||
let oidc_unverified =
|
||||
OidcUnverified::from_str(&id_token).expect("Failed to parse id_token");
|
||||
|
||||
let iat = ct.as_secs() as i64;
|
||||
|
||||
let oidc = oidc_unverified
|
||||
.validate(&jws_validator, iat)
|
||||
let oidc = jws_validator
|
||||
.verify(&oidc_unverified)
|
||||
.unwrap()
|
||||
.verify_exp(iat)
|
||||
.expect("Failed to verify oidc");
|
||||
|
||||
assert!(oidc.sub == OidcSubject::U(UUID_ADMIN));
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::time::Duration;
|
|||
|
||||
use base64urlsafedata::Base64UrlSafeData;
|
||||
|
||||
use compact_jwt::{Jws, JwsSigner};
|
||||
use compact_jwt::{Jws, JwsEs256Signer, JwsSigner};
|
||||
use kanidm_proto::internal::ScimSyncToken;
|
||||
use kanidm_proto::scim_v1::*;
|
||||
use kanidm_proto::v1::ApiTokenPurpose;
|
||||
|
@ -23,7 +23,7 @@ pub(crate) struct SyncAccount {
|
|||
pub name: String,
|
||||
pub uuid: Uuid,
|
||||
pub sync_tokens: BTreeMap<Uuid, ApiToken>,
|
||||
pub jws_key: JwsSigner,
|
||||
pub jws_key: JwsEs256Signer,
|
||||
}
|
||||
|
||||
macro_rules! try_from_entry {
|
||||
|
@ -48,7 +48,8 @@ macro_rules! try_from_entry {
|
|||
.ok_or(OperationError::InvalidAccountState(format!(
|
||||
"Missing attribute: {}",
|
||||
Attribute::JwsEs256PrivateKey
|
||||
)))?;
|
||||
)))?
|
||||
.set_sign_option_embed_jwk(true);
|
||||
|
||||
let sync_tokens = $value
|
||||
.get_ava_as_apitoken_map(Attribute::SyncTokenSession)
|
||||
|
@ -156,11 +157,16 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
},
|
||||
);
|
||||
|
||||
let token = Jws::new(ScimSyncToken {
|
||||
let scim_sync_token = ScimSyncToken {
|
||||
token_id: session_id,
|
||||
issued_at,
|
||||
purpose,
|
||||
});
|
||||
};
|
||||
|
||||
let token = Jws::into_json(&scim_sync_token).map_err(|err| {
|
||||
error!(?err, "Unable to serialise JWS");
|
||||
OperationError::SerdeJsonError
|
||||
})?;
|
||||
|
||||
let modlist = ModifyList::new_list(vec![Modify::Present(
|
||||
Attribute::SyncTokenSession.into(),
|
||||
|
@ -179,8 +185,9 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
)
|
||||
.and_then(|_| {
|
||||
// The modify succeeded and was allowed, now sign the token for return.
|
||||
token
|
||||
.sign_embed_public_jwk(&sync_account.jws_key)
|
||||
sync_account
|
||||
.jws_key
|
||||
.sign(&token)
|
||||
.map(|jws_signed| jws_signed.to_string())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Unable to sign sync token");
|
||||
|
@ -1517,7 +1524,7 @@ mod tests {
|
|||
use crate::idm::server::{IdmServerProxyWriteTransaction, IdmServerTransaction};
|
||||
use crate::prelude::*;
|
||||
use base64urlsafedata::Base64UrlSafeData;
|
||||
use compact_jwt::Jws;
|
||||
use compact_jwt::{Jws, JwsSigner};
|
||||
use kanidm_proto::scim_v1::*;
|
||||
use kanidm_proto::v1::ApiTokenPurpose;
|
||||
use std::sync::Arc;
|
||||
|
@ -1706,14 +1713,16 @@ mod tests {
|
|||
|
||||
let purpose = ApiTokenPurpose::ReadWrite;
|
||||
|
||||
let token = Jws::new(ScimSyncToken {
|
||||
let scim_sync_token = ScimSyncToken {
|
||||
token_id,
|
||||
issued_at,
|
||||
purpose,
|
||||
});
|
||||
};
|
||||
|
||||
let forged_token = token
|
||||
.sign(&jws_key)
|
||||
let token = Jws::into_json(&scim_sync_token).expect("Unable to serialise forged token");
|
||||
|
||||
let forged_token = jws_key
|
||||
.sign(&token)
|
||||
.map(|jws_signed| jws_signed.to_string())
|
||||
.expect("Unable to sign forged token");
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::time::Duration;
|
|||
|
||||
use kanidm_lib_crypto::CryptoPolicy;
|
||||
|
||||
use compact_jwt::{Jws, JwsSigner, JwsUnverified, JwsValidator};
|
||||
use compact_jwt::{JwsCompact, JwsEs256Signer, JwsEs256Verifier, JwsSignerToVerifier, JwsVerifier};
|
||||
use concread::bptree::{BptreeMap, BptreeMapReadTxn, BptreeMapWriteTxn};
|
||||
use concread::cowcell::{CowCellReadTxn, CowCellWriteTxn};
|
||||
use concread::hashmap::HashMap;
|
||||
|
@ -62,8 +62,8 @@ pub(crate) type CredSoftLockMutex = Arc<Mutex<CredSoftLock>>;
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct DomainKeys {
|
||||
pub(crate) uat_jwt_signer: JwsSigner,
|
||||
pub(crate) uat_jwt_validator: JwsValidator,
|
||||
pub(crate) uat_jwt_signer: JwsEs256Signer,
|
||||
pub(crate) uat_jwt_validator: JwsEs256Verifier,
|
||||
pub(crate) token_enc_key: Fernet,
|
||||
pub(crate) cookie_key: [u8; 64],
|
||||
}
|
||||
|
@ -205,12 +205,14 @@ impl IdmServer {
|
|||
OperationError::CryptographyError
|
||||
})?;
|
||||
|
||||
let uat_jwt_signer = JwsSigner::from_es256_der(&es256_private_key).map_err(|e| {
|
||||
admin_error!(err = ?e, "Unable to load ES256 JwsSigner from DER");
|
||||
OperationError::CryptographyError
|
||||
})?;
|
||||
let uat_jwt_signer = JwsEs256Signer::from_es256_der(&es256_private_key)
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Unable to load ES256 JwsSigner from DER");
|
||||
OperationError::CryptographyError
|
||||
})?
|
||||
.set_sign_option_embed_jwk(true);
|
||||
|
||||
let uat_jwt_validator = uat_jwt_signer.get_validator().map_err(|e| {
|
||||
let uat_jwt_validator = uat_jwt_signer.get_verifier().map_err(|e| {
|
||||
admin_error!(err = ?e, "Unable to load ES256 JwsValidator from JwsSigner");
|
||||
OperationError::CryptographyError
|
||||
})?;
|
||||
|
@ -394,7 +396,7 @@ pub trait IdmServerTransaction<'a> {
|
|||
|
||||
fn get_qs_txn(&mut self) -> &mut Self::QsTransactionType;
|
||||
|
||||
fn get_uat_validator_txn(&self) -> &JwsValidator;
|
||||
fn get_uat_validator_txn(&self) -> &JwsEs256Verifier;
|
||||
|
||||
/// This is the preferred method to transform and securely verify a token into
|
||||
/// an identity that can be used for operations and access enforcement. This
|
||||
|
@ -442,7 +444,7 @@ pub trait IdmServerTransaction<'a> {
|
|||
OperationError::NotAuthenticated
|
||||
})
|
||||
.and_then(|s| {
|
||||
JwsUnverified::from_str(s).map_err(|e| {
|
||||
JwsCompact::from_str(s).map_err(|e| {
|
||||
security_info!(?e, "Unable to decode token");
|
||||
OperationError::NotAuthenticated
|
||||
})
|
||||
|
@ -456,20 +458,25 @@ pub trait IdmServerTransaction<'a> {
|
|||
OperationError::NotAuthenticated
|
||||
})?;
|
||||
|
||||
let jwsv_kid = jws_validator.get_jwk_kid().ok_or_else(|| {
|
||||
let jwsv_kid = jws_validator.get_kid().ok_or_else(|| {
|
||||
security_info!("JWS validator does not contain a valid kid");
|
||||
OperationError::NotAuthenticated
|
||||
})?;
|
||||
|
||||
if kid == jwsv_kid {
|
||||
// It's signed by the primary jws, so it's probably a UserAuthToken.
|
||||
let uat = jwsu
|
||||
.validate(jws_validator)
|
||||
let uat = jws_validator
|
||||
.verify(&jwsu)
|
||||
.map_err(|e| {
|
||||
security_info!(?e, "Unable to verify token");
|
||||
OperationError::NotAuthenticated
|
||||
})
|
||||
.map(|t: Jws<UserAuthToken>| t.into_inner())?;
|
||||
.and_then(|t| {
|
||||
t.from_json::<UserAuthToken>().map_err(|err| {
|
||||
error!(?err, "Unable to deserialise JWS");
|
||||
OperationError::SerdeJsonError
|
||||
})
|
||||
})?;
|
||||
|
||||
if let Some(exp) = uat.expiry {
|
||||
let ct_odt = time::OffsetDateTime::UNIX_EPOCH + ct;
|
||||
|
@ -514,18 +521,23 @@ pub trait IdmServerTransaction<'a> {
|
|||
OperationError::NotAuthenticated
|
||||
})?;
|
||||
|
||||
let user_validator = user_signer.get_validator().map_err(|e| {
|
||||
let user_validator = user_signer.get_verifier().map_err(|e| {
|
||||
security_info!(?e, "Unable to access token verifier");
|
||||
OperationError::NotAuthenticated
|
||||
})?;
|
||||
|
||||
let apit = jwsu
|
||||
.validate(&user_validator)
|
||||
let apit = user_validator
|
||||
.verify(&jwsu)
|
||||
.map_err(|e| {
|
||||
security_info!(?e, "Unable to verify token");
|
||||
OperationError::NotAuthenticated
|
||||
})
|
||||
.map(|t: Jws<ApiToken>| t.into_inner())?;
|
||||
.and_then(|t| {
|
||||
t.from_json::<ApiToken>().map_err(|err| {
|
||||
error!(?err, "Unable to deserialise JWS");
|
||||
OperationError::SerdeJsonError
|
||||
})
|
||||
})?;
|
||||
|
||||
if let Some(expiry) = apit.expiry {
|
||||
if time::OffsetDateTime::UNIX_EPOCH + ct >= expiry {
|
||||
|
@ -550,18 +562,24 @@ pub trait IdmServerTransaction<'a> {
|
|||
let uat: UserAuthToken = token
|
||||
.ok_or(OperationError::NotAuthenticated)
|
||||
.and_then(|s| {
|
||||
JwsUnverified::from_str(s).map_err(|e| {
|
||||
JwsCompact::from_str(s).map_err(|e| {
|
||||
security_info!(?e, "Unable to decode token");
|
||||
OperationError::NotAuthenticated
|
||||
})
|
||||
})
|
||||
.and_then(|jwtu| {
|
||||
jwtu.validate(jws_validator)
|
||||
jws_validator
|
||||
.verify(&jwtu)
|
||||
.map_err(|e| {
|
||||
security_info!(?e, "Unable to verify token");
|
||||
OperationError::NotAuthenticated
|
||||
})
|
||||
.map(|t: Jws<UserAuthToken>| t.into_inner())
|
||||
.and_then(|t| {
|
||||
t.from_json::<UserAuthToken>().map_err(|err| {
|
||||
error!(?err, "Unable to deserialise JWS");
|
||||
OperationError::SerdeJsonError
|
||||
})
|
||||
})
|
||||
})?;
|
||||
|
||||
if let Some(exp) = uat.expiry {
|
||||
|
@ -833,7 +851,7 @@ pub trait IdmServerTransaction<'a> {
|
|||
OperationError::NotAuthenticated
|
||||
})
|
||||
.and_then(|s| {
|
||||
JwsUnverified::from_str(s).map_err(|e| {
|
||||
JwsCompact::from_str(s).map_err(|e| {
|
||||
security_info!(?e, "Unable to decode token");
|
||||
OperationError::NotAuthenticated
|
||||
})
|
||||
|
@ -872,18 +890,23 @@ pub trait IdmServerTransaction<'a> {
|
|||
OperationError::NotAuthenticated
|
||||
})?;
|
||||
|
||||
let user_validator = user_signer.get_validator().map_err(|e| {
|
||||
let user_validator = user_signer.get_verifier().map_err(|e| {
|
||||
security_info!(?e, "Unable to access token verifier");
|
||||
OperationError::NotAuthenticated
|
||||
})?;
|
||||
|
||||
let sync_token = jwsu
|
||||
.validate(&user_validator)
|
||||
let sync_token = user_validator
|
||||
.verify(&jwsu)
|
||||
.map_err(|e| {
|
||||
security_info!(?e, "Unable to verify token");
|
||||
OperationError::NotAuthenticated
|
||||
})
|
||||
.map(|t: Jws<ScimSyncToken>| t.into_inner())?;
|
||||
.and_then(|t| {
|
||||
t.from_json::<ScimSyncToken>().map_err(|err| {
|
||||
error!(?err, "Unable to deserialise JWS");
|
||||
OperationError::SerdeJsonError
|
||||
})
|
||||
})?;
|
||||
|
||||
let valid = SyncAccount::check_sync_token_valid(ct, &sync_token, &entry);
|
||||
|
||||
|
@ -912,7 +935,7 @@ impl<'a> IdmServerTransaction<'a> for IdmServerAuthTransaction<'a> {
|
|||
&mut self.qs_read
|
||||
}
|
||||
|
||||
fn get_uat_validator_txn(&self) -> &JwsValidator {
|
||||
fn get_uat_validator_txn(&self) -> &JwsEs256Verifier {
|
||||
&self.domain_keys.uat_jwt_validator
|
||||
}
|
||||
}
|
||||
|
@ -1429,7 +1452,7 @@ impl<'a> IdmServerTransaction<'a> for IdmServerProxyReadTransaction<'a> {
|
|||
&mut self.qs_read
|
||||
}
|
||||
|
||||
fn get_uat_validator_txn(&self) -> &JwsValidator {
|
||||
fn get_uat_validator_txn(&self) -> &JwsEs256Verifier {
|
||||
&self.domain_keys.uat_jwt_validator
|
||||
}
|
||||
}
|
||||
|
@ -1532,7 +1555,7 @@ impl<'a> IdmServerTransaction<'a> for IdmServerProxyWriteTransaction<'a> {
|
|||
&mut self.qs_write
|
||||
}
|
||||
|
||||
fn get_uat_validator_txn(&self) -> &JwsValidator {
|
||||
fn get_uat_validator_txn(&self) -> &JwsEs256Verifier {
|
||||
&self.domain_keys.uat_jwt_validator
|
||||
}
|
||||
}
|
||||
|
@ -2035,14 +2058,16 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
self.qs_write
|
||||
.get_domain_es256_private_key()
|
||||
.and_then(|key_der| {
|
||||
JwsSigner::from_es256_der(&key_der).map_err(|e| {
|
||||
admin_error!("Failed to generate uat_jwt_signer - {:?}", e);
|
||||
OperationError::InvalidState
|
||||
})
|
||||
JwsEs256Signer::from_es256_der(&key_der)
|
||||
.map(|signer| signer.set_sign_option_embed_jwk(true))
|
||||
.map_err(|e| {
|
||||
admin_error!("Failed to generate uat_jwt_signer - {:?}", e);
|
||||
OperationError::InvalidState
|
||||
})
|
||||
})
|
||||
.and_then(|signer| {
|
||||
signer
|
||||
.get_validator()
|
||||
.get_verifier()
|
||||
.map_err(|e| {
|
||||
admin_error!("Failed to generate uat_jwt_validator - {:?}", e);
|
||||
OperationError::InvalidState
|
||||
|
@ -2100,6 +2125,7 @@ mod tests {
|
|||
use crate::modify::{Modify, ModifyList};
|
||||
use crate::prelude::*;
|
||||
use crate::value::SessionState;
|
||||
use compact_jwt::{JwsCompact, JwsEs256Verifier, JwsVerifier};
|
||||
use kanidm_lib_crypto::CryptoPolicy;
|
||||
|
||||
const TEST_PASSWORD: &str = "ntaoeuntnaoeuhraohuercahu😍";
|
||||
|
@ -3474,7 +3500,6 @@ mod tests {
|
|||
idms: &IdmServer,
|
||||
idms_delayed: &mut IdmServerDelayed,
|
||||
) {
|
||||
use compact_jwt::{Jws, JwsUnverified};
|
||||
use kanidm_proto::v1::UserAuthToken;
|
||||
use std::str::FromStr;
|
||||
|
||||
|
@ -3499,11 +3524,16 @@ mod tests {
|
|||
let r = idms.delayed_action(ct, da).await;
|
||||
assert!(Ok(true) == r);
|
||||
|
||||
let uat_unverified = JwsUnverified::from_str(&token).expect("Failed to parse apitoken");
|
||||
let uat_inner: Jws<UserAuthToken> = uat_unverified
|
||||
.validate_embeded()
|
||||
.expect("Embedded jwk not found");
|
||||
let uat_inner = uat_inner.into_inner();
|
||||
let uat_unverified = JwsCompact::from_str(&token).expect("Failed to parse apitoken");
|
||||
|
||||
let jws_validator =
|
||||
JwsEs256Verifier::try_from(uat_unverified.get_jwk_pubkey().unwrap()).unwrap();
|
||||
|
||||
let uat_inner: UserAuthToken = jws_validator
|
||||
.verify(&uat_unverified)
|
||||
.unwrap()
|
||||
.from_json()
|
||||
.unwrap();
|
||||
|
||||
let mut idms_prox_read = idms.proxy_read().await;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use compact_jwt::{Jws, JwsSigner};
|
||||
use compact_jwt::{Jws, JwsEs256Signer, JwsSigner};
|
||||
use kanidm_proto::v1::ApiToken as ProtoApiToken;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
|
@ -48,7 +48,8 @@ macro_rules! try_from_entry {
|
|||
.ok_or(OperationError::InvalidAccountState(format!(
|
||||
"Missing attribute: {}",
|
||||
Attribute::JwsEs256PrivateKey
|
||||
)))?;
|
||||
)))?
|
||||
.set_sign_option_embed_jwk(true);
|
||||
|
||||
let api_tokens = $value
|
||||
.get_ava_as_apitoken_map(Attribute::ApiTokenSession)
|
||||
|
@ -81,7 +82,7 @@ pub struct ServiceAccount {
|
|||
|
||||
pub api_tokens: BTreeMap<Uuid, ApiToken>,
|
||||
|
||||
pub jws_key: JwsSigner,
|
||||
pub jws_key: JwsEs256Signer,
|
||||
}
|
||||
|
||||
impl ServiceAccount {
|
||||
|
@ -240,14 +241,19 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
);
|
||||
|
||||
// create the session token (not yet signed)
|
||||
let token = Jws::new(ProtoApiToken {
|
||||
let proto_api_token = ProtoApiToken {
|
||||
account_id: service_account.uuid,
|
||||
token_id: session_id,
|
||||
label: gte.label.clone(),
|
||||
expiry: gte.expiry,
|
||||
issued_at,
|
||||
purpose,
|
||||
});
|
||||
};
|
||||
|
||||
let token = Jws::into_json(&proto_api_token).map_err(|err| {
|
||||
error!(?err, "Unable to serialise JWS");
|
||||
OperationError::SerdeJsonError
|
||||
})?;
|
||||
|
||||
// modify the account to put the session onto it.
|
||||
let modlist = ModifyList::new_list(vec![Modify::Present(
|
||||
|
@ -267,8 +273,9 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
)
|
||||
.and_then(|_| {
|
||||
// The modify succeeded and was allowed, now sign the token for return.
|
||||
token
|
||||
.sign_embed_public_jwk(&service_account.jws_key)
|
||||
service_account
|
||||
.jws_key
|
||||
.sign(&token)
|
||||
.map(|jws_signed| jws_signed.to_string())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Unable to sign api token");
|
||||
|
@ -424,7 +431,7 @@ mod tests {
|
|||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use compact_jwt::{Jws, JwsUnverified};
|
||||
use compact_jwt::{JwsCompact, JwsEs256Verifier, JwsVerifier};
|
||||
use kanidm_proto::v1::ApiToken;
|
||||
|
||||
use super::{DestroyApiTokenEvent, GenerateApiTokenEvent};
|
||||
|
@ -471,11 +478,16 @@ mod tests {
|
|||
|
||||
// Deserialise it.
|
||||
let apitoken_unverified =
|
||||
JwsUnverified::from_str(&api_token).expect("Failed to parse apitoken");
|
||||
let apitoken_inner: Jws<ApiToken> = apitoken_unverified
|
||||
.validate_embeded()
|
||||
.expect("Embedded jwk not found");
|
||||
let apitoken_inner = apitoken_inner.into_inner();
|
||||
JwsCompact::from_str(&api_token).expect("Failed to parse apitoken");
|
||||
|
||||
let jws_verifier =
|
||||
JwsEs256Verifier::try_from(apitoken_unverified.get_jwk_pubkey().unwrap()).unwrap();
|
||||
|
||||
let apitoken_inner = jws_verifier
|
||||
.verify(&apitoken_unverified)
|
||||
.unwrap()
|
||||
.from_json::<ApiToken>()
|
||||
.unwrap();
|
||||
|
||||
let ident = idms_prox_write
|
||||
.validate_and_parse_token_to_ident(Some(&api_token), ct)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
use std::iter::once;
|
||||
use std::sync::Arc;
|
||||
|
||||
use compact_jwt::JwsSigner;
|
||||
use compact_jwt::JwsEs256Signer;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use rand::prelude::*;
|
||||
use regex::Regex;
|
||||
|
@ -126,7 +126,7 @@ impl Domain {
|
|||
|
||||
if !e.attribute_pres(Attribute::Es256PrivateKeyDer) {
|
||||
security_info!("regenerating domain es256 private key");
|
||||
let der = JwsSigner::generate_es256()
|
||||
let der = JwsEs256Signer::generate_es256()
|
||||
.and_then(|jws| jws.private_key_to_der())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Unable to generate ES256 JwsSigner private key");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use compact_jwt::JwsSigner;
|
||||
use compact_jwt::{crypto::JwsRs256Signer, JwsEs256Signer};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
|
@ -62,7 +62,7 @@ impl JwsKeygen {
|
|||
}
|
||||
if !e.attribute_pres(Attribute::Es256PrivateKeyDer) {
|
||||
security_info!("regenerating oauth2 es256 private key");
|
||||
let der = JwsSigner::generate_es256()
|
||||
let der = JwsEs256Signer::generate_es256()
|
||||
.and_then(|jws| jws.private_key_to_der())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Unable to generate ES256 JwsSigner private key");
|
||||
|
@ -74,7 +74,7 @@ impl JwsKeygen {
|
|||
if e.get_ava_single_bool(Attribute::OAuth2JwtLegacyCryptoEnable).unwrap_or(false)
|
||||
&& !e.attribute_pres(Attribute::Rs256PrivateKeyDer) {
|
||||
security_info!("regenerating oauth2 legacy rs256 private key");
|
||||
let der = JwsSigner::generate_legacy_rs256()
|
||||
let der = JwsRs256Signer::generate_legacy_rs256()
|
||||
.and_then(|jws| jws.private_key_to_der())
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Unable to generate Legacy RS256 JwsSigner private key");
|
||||
|
@ -89,7 +89,7 @@ impl JwsKeygen {
|
|||
e.attribute_equality(Attribute::Class, &EntryClass::SyncAccount.into())) &&
|
||||
!e.attribute_pres(Attribute::JwsEs256PrivateKey) {
|
||||
security_info!("regenerating jws es256 private key");
|
||||
let jwssigner = JwsSigner::generate_es256()
|
||||
let jwssigner = JwsEs256Signer::generate_es256()
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Unable to generate ES256 JwsSigner private key");
|
||||
OperationError::CryptographyError
|
||||
|
|
|
@ -15,7 +15,7 @@ use std::time::Duration;
|
|||
|
||||
#[cfg(test)]
|
||||
use base64::{engine::general_purpose, Engine as _};
|
||||
use compact_jwt::JwsSigner;
|
||||
use compact_jwt::{crypto::JwsRs256Signer, JwsEs256Signer};
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::internal::ImageValue;
|
||||
use num_enum::TryFromPrimitive;
|
||||
|
@ -1029,8 +1029,8 @@ pub enum Value {
|
|||
ApiToken(Uuid, ApiToken),
|
||||
Oauth2Session(Uuid, Oauth2Session),
|
||||
|
||||
JwsKeyEs256(JwsSigner),
|
||||
JwsKeyRs256(JwsSigner),
|
||||
JwsKeyEs256(JwsEs256Signer),
|
||||
JwsKeyRs256(JwsRs256Signer),
|
||||
UiHint(UiHint),
|
||||
|
||||
TotpSecret(String, Totp),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use base64urlsafedata::Base64UrlSafeData;
|
||||
use compact_jwt::{JwaAlg, JwsSigner};
|
||||
use compact_jwt::{crypto::JwsRs256Signer, JwsEs256Signer, JwsSigner};
|
||||
use hashbrown::HashSet;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
@ -9,19 +9,17 @@ use crate::valueset::{DbValueSetV2, ValueSet};
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetJwsKeyEs256 {
|
||||
set: HashSet<JwsSigner>,
|
||||
set: HashSet<JwsEs256Signer>,
|
||||
}
|
||||
|
||||
impl ValueSetJwsKeyEs256 {
|
||||
pub fn new(k: JwsSigner) -> Box<Self> {
|
||||
debug_assert!(k.get_jwa_alg() == JwaAlg::ES256);
|
||||
pub fn new(k: JwsEs256Signer) -> Box<Self> {
|
||||
let mut set = HashSet::new();
|
||||
set.insert(k);
|
||||
Box::new(ValueSetJwsKeyEs256 { set })
|
||||
}
|
||||
|
||||
pub fn push(&mut self, k: JwsSigner) -> bool {
|
||||
debug_assert!(k.get_jwa_alg() == JwaAlg::ES256);
|
||||
pub fn push(&mut self, k: JwsEs256Signer) -> bool {
|
||||
self.set.insert(k)
|
||||
}
|
||||
|
||||
|
@ -29,7 +27,7 @@ impl ValueSetJwsKeyEs256 {
|
|||
let set = data
|
||||
.iter()
|
||||
.map(|b| {
|
||||
JwsSigner::from_es256_der(b).map_err(|e| {
|
||||
JwsEs256Signer::from_es256_der(b).map_err(|e| {
|
||||
debug!(?e, "Error occurred parsing ES256 DER");
|
||||
OperationError::InvalidValueState
|
||||
})
|
||||
|
@ -42,7 +40,7 @@ impl ValueSetJwsKeyEs256 {
|
|||
let set = data
|
||||
.iter()
|
||||
.map(|b| {
|
||||
JwsSigner::from_es256_der(b.0.as_slice()).map_err(|e| {
|
||||
JwsEs256Signer::from_es256_der(b.0.as_slice()).map_err(|e| {
|
||||
debug!(?e, "Error occurred parsing ES256 DER");
|
||||
OperationError::InvalidValueState
|
||||
})
|
||||
|
@ -56,10 +54,9 @@ impl ValueSetJwsKeyEs256 {
|
|||
#[allow(clippy::should_implement_trait)]
|
||||
pub fn from_iter<T>(iter: T) -> Option<Box<ValueSetJwsKeyEs256>>
|
||||
where
|
||||
T: IntoIterator<Item = JwsSigner>,
|
||||
T: IntoIterator<Item = JwsEs256Signer>,
|
||||
{
|
||||
let set: HashSet<JwsSigner> = iter.into_iter().collect();
|
||||
debug_assert!(set.iter().all(|k| k.get_jwa_alg() == JwaAlg::ES256));
|
||||
let set: HashSet<JwsEs256Signer> = iter.into_iter().collect();
|
||||
Some(Box::new(ValueSetJwsKeyEs256 { set }))
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +123,7 @@ impl ValueSetT for ValueSetJwsKeyEs256 {
|
|||
}
|
||||
|
||||
fn validate(&self, _schema_attr: &SchemaAttribute) -> bool {
|
||||
self.set.iter().all(|k| k.get_jwa_alg() == JwaAlg::ES256)
|
||||
true
|
||||
}
|
||||
|
||||
fn to_proto_string_clone_iter(&self) -> Box<dyn Iterator<Item = String> + '_> {
|
||||
|
@ -186,7 +183,7 @@ impl ValueSetT for ValueSetJwsKeyEs256 {
|
|||
}
|
||||
}
|
||||
|
||||
fn to_jws_key_es256_single(&self) -> Option<&JwsSigner> {
|
||||
fn to_jws_key_es256_single(&self) -> Option<&JwsEs256Signer> {
|
||||
if self.set.len() == 1 {
|
||||
self.set.iter().take(1).next()
|
||||
} else {
|
||||
|
@ -194,26 +191,24 @@ impl ValueSetT for ValueSetJwsKeyEs256 {
|
|||
}
|
||||
}
|
||||
|
||||
fn as_jws_key_es256_set(&self) -> Option<&HashSet<JwsSigner>> {
|
||||
fn as_jws_key_es256_set(&self) -> Option<&HashSet<JwsEs256Signer>> {
|
||||
Some(&self.set)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ValueSetJwsKeyRs256 {
|
||||
set: HashSet<JwsSigner>,
|
||||
set: HashSet<JwsRs256Signer>,
|
||||
}
|
||||
|
||||
impl ValueSetJwsKeyRs256 {
|
||||
pub fn new(k: JwsSigner) -> Box<Self> {
|
||||
debug_assert!(k.get_jwa_alg() == JwaAlg::RS256);
|
||||
pub fn new(k: JwsRs256Signer) -> Box<Self> {
|
||||
let mut set = HashSet::new();
|
||||
set.insert(k);
|
||||
Box::new(ValueSetJwsKeyRs256 { set })
|
||||
}
|
||||
|
||||
pub fn push(&mut self, k: JwsSigner) -> bool {
|
||||
debug_assert!(k.get_jwa_alg() == JwaAlg::RS256);
|
||||
pub fn push(&mut self, k: JwsRs256Signer) -> bool {
|
||||
self.set.insert(k)
|
||||
}
|
||||
|
||||
|
@ -221,7 +216,7 @@ impl ValueSetJwsKeyRs256 {
|
|||
let set = data
|
||||
.iter()
|
||||
.map(|b| {
|
||||
JwsSigner::from_rs256_der(b).map_err(|e| {
|
||||
JwsRs256Signer::from_rs256_der(b).map_err(|e| {
|
||||
debug!(?e, "Error occurred parsing RS256 DER");
|
||||
OperationError::InvalidValueState
|
||||
})
|
||||
|
@ -234,7 +229,7 @@ impl ValueSetJwsKeyRs256 {
|
|||
let set = data
|
||||
.iter()
|
||||
.map(|b| {
|
||||
JwsSigner::from_rs256_der(b.0.as_slice()).map_err(|e| {
|
||||
JwsRs256Signer::from_rs256_der(b.0.as_slice()).map_err(|e| {
|
||||
debug!(?e, "Error occurred parsing RS256 DER");
|
||||
OperationError::InvalidValueState
|
||||
})
|
||||
|
@ -248,10 +243,9 @@ impl ValueSetJwsKeyRs256 {
|
|||
#[allow(clippy::should_implement_trait)]
|
||||
pub fn from_iter<T>(iter: T) -> Option<Box<ValueSetJwsKeyRs256>>
|
||||
where
|
||||
T: IntoIterator<Item = JwsSigner>,
|
||||
T: IntoIterator<Item = JwsRs256Signer>,
|
||||
{
|
||||
let set: HashSet<JwsSigner> = iter.into_iter().collect();
|
||||
debug_assert!(set.iter().all(|k| k.get_jwa_alg() == JwaAlg::RS256));
|
||||
let set: HashSet<JwsRs256Signer> = iter.into_iter().collect();
|
||||
Some(Box::new(ValueSetJwsKeyRs256 { set }))
|
||||
}
|
||||
}
|
||||
|
@ -315,7 +309,7 @@ impl ValueSetT for ValueSetJwsKeyRs256 {
|
|||
}
|
||||
|
||||
fn validate(&self, _schema_attr: &SchemaAttribute) -> bool {
|
||||
self.set.iter().all(|k| k.get_jwa_alg() == JwaAlg::RS256)
|
||||
true
|
||||
}
|
||||
|
||||
fn to_proto_string_clone_iter(&self) -> Box<dyn Iterator<Item = String> + '_> {
|
||||
|
@ -375,7 +369,7 @@ impl ValueSetT for ValueSetJwsKeyRs256 {
|
|||
}
|
||||
}
|
||||
|
||||
fn to_jws_key_rs256_single(&self) -> Option<&JwsSigner> {
|
||||
fn to_jws_key_rs256_single(&self) -> Option<&JwsRs256Signer> {
|
||||
if self.set.len() == 1 {
|
||||
self.set.iter().take(1).next()
|
||||
} else {
|
||||
|
@ -383,7 +377,7 @@ impl ValueSetT for ValueSetJwsKeyRs256 {
|
|||
}
|
||||
}
|
||||
|
||||
fn as_jws_key_rs256_set(&self) -> Option<&HashSet<JwsSigner>> {
|
||||
fn as_jws_key_rs256_set(&self) -> Option<&HashSet<JwsRs256Signer>> {
|
||||
Some(&self.set)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
use compact_jwt::JwsSigner;
|
||||
use compact_jwt::{crypto::JwsRs256Signer, JwsEs256Signer};
|
||||
use dyn_clone::DynClone;
|
||||
use hashbrown::HashSet;
|
||||
use kanidm_proto::internal::ImageValue;
|
||||
|
@ -527,7 +527,7 @@ pub trait ValueSetT: std::fmt::Debug + DynClone {
|
|||
None
|
||||
}
|
||||
|
||||
fn to_jws_key_es256_single(&self) -> Option<&JwsSigner> {
|
||||
fn to_jws_key_es256_single(&self) -> Option<&JwsEs256Signer> {
|
||||
debug_assert!(false);
|
||||
None
|
||||
}
|
||||
|
@ -542,17 +542,17 @@ pub trait ValueSetT: std::fmt::Debug + DynClone {
|
|||
None
|
||||
}
|
||||
|
||||
fn as_jws_key_es256_set(&self) -> Option<&HashSet<JwsSigner>> {
|
||||
fn as_jws_key_es256_set(&self) -> Option<&HashSet<JwsEs256Signer>> {
|
||||
debug_assert!(false);
|
||||
None
|
||||
}
|
||||
|
||||
fn to_jws_key_rs256_single(&self) -> Option<&JwsSigner> {
|
||||
fn to_jws_key_rs256_single(&self) -> Option<&JwsRs256Signer> {
|
||||
debug_assert!(false);
|
||||
None
|
||||
}
|
||||
|
||||
fn as_jws_key_rs256_set(&self) -> Option<&HashSet<JwsSigner>> {
|
||||
fn as_jws_key_rs256_set(&self) -> Option<&HashSet<JwsRs256Signer>> {
|
||||
debug_assert!(false);
|
||||
None
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
|||
use std::convert::TryFrom;
|
||||
use std::str::FromStr;
|
||||
|
||||
use compact_jwt::{JwkKeySet, JwsValidator, OidcToken, OidcUnverified};
|
||||
use compact_jwt::{JwkKeySet, JwsEs256Verifier, JwsVerifier, OidcToken, OidcUnverified};
|
||||
use kanidm_proto::constants::uri::{OAUTH2_AUTHORISE, OAUTH2_AUTHORISE_PERMIT};
|
||||
use kanidm_proto::constants::*;
|
||||
use kanidm_proto::oauth2::{
|
||||
|
@ -211,7 +211,7 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) {
|
|||
|
||||
let public_jwk = jwk_set.keys.pop().expect("No public key in set!");
|
||||
|
||||
let jws_validator = JwsValidator::try_from(&public_jwk).expect("failed to build validator");
|
||||
let jws_validator = JwsEs256Verifier::try_from(&public_jwk).expect("failed to build validator");
|
||||
|
||||
// Step 1 - the Oauth2 Resource Server would send a redirect to the authorisation
|
||||
// server, where the url contains a series of authorisation request parameters.
|
||||
|
@ -366,9 +366,11 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) {
|
|||
let oidc_unverified =
|
||||
OidcUnverified::from_str(atr.id_token.as_ref().unwrap()).expect("Failed to parse id_token");
|
||||
|
||||
let oidc = oidc_unverified
|
||||
.validate(&jws_validator, 0)
|
||||
.expect("Failed to verify oidc");
|
||||
let oidc = jws_validator
|
||||
.verify(&oidc_unverified)
|
||||
.expect("Failed to verify oidc")
|
||||
.verify_exp(0)
|
||||
.expect("Failed to check exp");
|
||||
|
||||
// This is mostly checked inside of idm/oauth2.rs. This is more to check the oidc
|
||||
// token and the userinfo endpoints.
|
||||
|
@ -512,7 +514,7 @@ async fn test_oauth2_openid_public_flow(rsclient: KanidmClient) {
|
|||
|
||||
let public_jwk = jwk_set.keys.pop().expect("No public key in set!");
|
||||
|
||||
let jws_validator = JwsValidator::try_from(&public_jwk).expect("failed to build validator");
|
||||
let jws_validator = JwsEs256Verifier::try_from(&public_jwk).expect("failed to build validator");
|
||||
|
||||
// Step 1 - the Oauth2 Resource Server would send a redirect to the authorisation
|
||||
// server, where the url contains a series of authorisation request parameters.
|
||||
|
@ -624,9 +626,11 @@ async fn test_oauth2_openid_public_flow(rsclient: KanidmClient) {
|
|||
let oidc_unverified =
|
||||
OidcUnverified::from_str(atr.id_token.as_ref().unwrap()).expect("Failed to parse id_token");
|
||||
|
||||
let oidc = oidc_unverified
|
||||
.validate(&jws_validator, 0)
|
||||
.expect("Failed to verify oidc");
|
||||
let oidc = jws_validator
|
||||
.verify(&oidc_unverified)
|
||||
.expect("Failed to verify oidc")
|
||||
.verify_exp(0)
|
||||
.expect("Failed to check exp");
|
||||
|
||||
// This is mostly checked inside of idm/oauth2.rs. This is more to check the oidc
|
||||
// token and the userinfo endpoints.
|
||||
|
|
|
@ -18,7 +18,7 @@ use tracing::{debug, trace};
|
|||
|
||||
use std::str::FromStr;
|
||||
|
||||
use compact_jwt::JwsUnverified;
|
||||
use compact_jwt::{JwsCompact, JwsEs256Verifier, JwsVerifier};
|
||||
use webauthn_authenticator_rs::softpasskey::SoftPasskey;
|
||||
use webauthn_authenticator_rs::WebauthnAuthenticator;
|
||||
|
||||
|
@ -1445,12 +1445,19 @@ async fn test_server_api_token_lifecycle(rsclient: KanidmClient) {
|
|||
.expect("Failed to create service account api token");
|
||||
|
||||
// Decode it?
|
||||
let token_unverified = JwsUnverified::from_str(&token).expect("Failed to parse apitoken");
|
||||
let token_unverified = JwsCompact::from_str(&token).expect("Failed to parse apitoken");
|
||||
|
||||
let token: ApiToken = token_unverified
|
||||
.validate_embeded()
|
||||
.map(|j| j.into_inner())
|
||||
.expect("Embedded jwk not found");
|
||||
let jws_verifier = JwsEs256Verifier::try_from(
|
||||
token_unverified
|
||||
.get_jwk_pubkey()
|
||||
.expect("No pubkey in token"),
|
||||
)
|
||||
.expect("Unable to build verifier");
|
||||
|
||||
let token = jws_verifier
|
||||
.verify(&token_unverified)
|
||||
.map(|j| j.from_json::<ApiToken>().expect("invalid token json"))
|
||||
.expect("Failed to verify token");
|
||||
|
||||
let tokens = rsclient
|
||||
.idm_service_account_list_api_token(test_service_account_username)
|
||||
|
@ -1649,13 +1656,16 @@ async fn test_server_user_auth_token_lifecycle(rsclient: KanidmClient) {
|
|||
|
||||
let token = rsclient.get_token().await.expect("No bearer token present");
|
||||
|
||||
let token_unverified =
|
||||
JwsUnverified::from_str(&token).expect("Failed to parse user auth token");
|
||||
let jwt = JwsCompact::from_str(&token).expect("Failed to parse jwt");
|
||||
|
||||
let token: UserAuthToken = token_unverified
|
||||
.validate_embeded()
|
||||
.map(|j| j.into_inner())
|
||||
.expect("Embedded jwk not found");
|
||||
let jws_verifier =
|
||||
JwsEs256Verifier::try_from(jwt.get_jwk_pubkey().expect("No pubkey in token"))
|
||||
.expect("Unable to build verifier");
|
||||
|
||||
let token: UserAuthToken = jws_verifier
|
||||
.verify(&jwt)
|
||||
.map(|jws| jws.from_json::<UserAuthToken>().expect("Invalid json"))
|
||||
.expect("Unable extract uat");
|
||||
|
||||
let sessions = rsclient
|
||||
.idm_account_list_user_auth_token("demo_account")
|
||||
|
@ -1719,12 +1729,17 @@ async fn test_server_user_auth_reauthentication(rsclient: KanidmClient) {
|
|||
.get_token()
|
||||
.await
|
||||
.expect("Must have a bearer token");
|
||||
let jwtu = JwsUnverified::from_str(&token).expect("Failed to parse jwsu");
|
||||
|
||||
let uat: UserAuthToken = jwtu
|
||||
.validate_embeded()
|
||||
.map(|jws| jws.into_inner())
|
||||
.expect("Unable to open up token.");
|
||||
let jwt = JwsCompact::from_str(&token).expect("Failed to parse jwt");
|
||||
|
||||
let jws_verifier =
|
||||
JwsEs256Verifier::try_from(jwt.get_jwk_pubkey().expect("No pubkey in token"))
|
||||
.expect("Unable to build verifier");
|
||||
|
||||
let uat: UserAuthToken = jws_verifier
|
||||
.verify(&jwt)
|
||||
.map(|jws| jws.from_json::<UserAuthToken>().expect("Invalid json"))
|
||||
.expect("Unable extract uat");
|
||||
|
||||
let now = time::OffsetDateTime::now_utc();
|
||||
assert!(!uat.purpose_readwrite_active(now));
|
||||
|
@ -1754,12 +1769,17 @@ async fn test_server_user_auth_reauthentication(rsclient: KanidmClient) {
|
|||
.get_token()
|
||||
.await
|
||||
.expect("Must have a bearer token");
|
||||
let jwtu = JwsUnverified::from_str(&token).expect("Failed to parse jwsu");
|
||||
|
||||
let uat: UserAuthToken = jwtu
|
||||
.validate_embeded()
|
||||
.map(|jws| jws.into_inner())
|
||||
.expect("Unable to open up token.");
|
||||
let jwt = JwsCompact::from_str(&token).expect("Failed to parse jwt");
|
||||
|
||||
let jws_verifier =
|
||||
JwsEs256Verifier::try_from(jwt.get_jwk_pubkey().expect("No pubkey in token"))
|
||||
.expect("Unable to build verifier");
|
||||
|
||||
let uat: UserAuthToken = jws_verifier
|
||||
.verify(&jwt)
|
||||
.map(|jws| jws.from_json::<UserAuthToken>().expect("Invalid json"))
|
||||
.expect("Unable extract uat");
|
||||
|
||||
let now = time::OffsetDateTime::now_utc();
|
||||
eprintln!("{:?} {:?}", now, uat.purpose);
|
||||
|
@ -1839,10 +1859,15 @@ async fn start_password_session(
|
|||
_ => panic!("Failed to extract jwt"),
|
||||
};
|
||||
|
||||
let jwt = JwsUnverified::from_str(&jwt).expect("Failed to parse jwt");
|
||||
let uat: UserAuthToken = jwt
|
||||
.validate_embeded()
|
||||
.map(|jws| jws.into_inner())
|
||||
let jwt = JwsCompact::from_str(&jwt).expect("Failed to parse jwt");
|
||||
|
||||
let jws_verifier =
|
||||
JwsEs256Verifier::try_from(jwt.get_jwk_pubkey().expect("No pubkey in token"))
|
||||
.expect("Unable to build verifier");
|
||||
|
||||
let uat: UserAuthToken = jws_verifier
|
||||
.verify(&jwt)
|
||||
.map(|jws| jws.from_json::<UserAuthToken>().expect("Invalid json"))
|
||||
.expect("Unable extract uat");
|
||||
|
||||
Ok(uat)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use compact_jwt::JwsUnverified;
|
||||
use compact_jwt::{JwsCompact, JwsEs256Verifier, JwsVerifier};
|
||||
use kanidm_client::KanidmClient;
|
||||
use kanidm_proto::internal::ScimSyncToken;
|
||||
use kanidmd_testkit::{ADMIN_TEST_PASSWORD, ADMIN_TEST_USER};
|
||||
|
@ -75,12 +75,19 @@ async fn test_sync_account_lifecycle(rsclient: KanidmClient) {
|
|||
.await
|
||||
.expect("Failed to generate token");
|
||||
|
||||
let token_unverified = JwsUnverified::from_str(&token).expect("Failed to parse apitoken");
|
||||
let token_unverified = JwsCompact::from_str(&token).expect("Failed to parse apitoken");
|
||||
|
||||
let token: ScimSyncToken = token_unverified
|
||||
.validate_embeded()
|
||||
.map(|j| j.into_inner())
|
||||
.expect("Embedded jwk not found");
|
||||
let jws_verifier = JwsEs256Verifier::try_from(
|
||||
token_unverified
|
||||
.get_jwk_pubkey()
|
||||
.expect("No pubkey in token"),
|
||||
)
|
||||
.expect("Unable to build verifier");
|
||||
|
||||
let token = jws_verifier
|
||||
.verify(&token_unverified)
|
||||
.map(|jws| jws.from_json::<ScimSyncToken>().expect("Invalid json"))
|
||||
.expect("Unable verify token");
|
||||
|
||||
println!("{:?}", token);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::env;
|
|||
use std::str::FromStr;
|
||||
|
||||
use async_recursion::async_recursion;
|
||||
use compact_jwt::{Jws, JwsUnverified};
|
||||
use compact_jwt::{JwsCompact, JwsEs256Verifier, JwsVerifier, JwtError};
|
||||
use dialoguer::theme::ColorfulTheme;
|
||||
use dialoguer::{Confirm, Select};
|
||||
use kanidm_client::{KanidmClient, KanidmClientBuilder};
|
||||
|
@ -198,7 +198,7 @@ impl CommonOpt {
|
|||
}
|
||||
};
|
||||
|
||||
let jwtu = match JwsUnverified::from_str(&token) {
|
||||
let jwsc = match JwsCompact::from_str(&token) {
|
||||
Ok(jwtu) => jwtu,
|
||||
Err(e) => {
|
||||
error!("Unable to parse token - {:?}", e);
|
||||
|
@ -207,10 +207,25 @@ impl CommonOpt {
|
|||
};
|
||||
|
||||
// Is the token (probably) valid?
|
||||
match jwtu
|
||||
.validate_embeded()
|
||||
.map(|jws: Jws<UserAuthToken>| jws.into_inner())
|
||||
{
|
||||
let jws_verifier = if let Some(pub_jwk) = jwsc.get_jwk_pubkey() {
|
||||
match JwsEs256Verifier::try_from(pub_jwk) {
|
||||
Ok(verifier) => verifier,
|
||||
Err(err) => {
|
||||
error!(?err, "Unable to configure jws verifier");
|
||||
return Err(ToClientError::Other);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error!("Unable to access token public key");
|
||||
return Err(ToClientError::Other);
|
||||
};
|
||||
|
||||
match jws_verifier.verify(&jwsc).and_then(|jws| {
|
||||
jws.from_json::<UserAuthToken>().map_err(|serde_err| {
|
||||
error!(?serde_err);
|
||||
JwtError::InvalidJwt
|
||||
})
|
||||
}) {
|
||||
Ok(uat) => {
|
||||
let now_utc = time::OffsetDateTime::now_utc();
|
||||
if let Some(exp) = uat.expiry {
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::io::{self, BufReader, BufWriter, ErrorKind, IsTerminal, Write};
|
|||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
use compact_jwt::{Jws, JwsUnverified};
|
||||
use compact_jwt::{JwsCompact, JwsEs256Verifier, JwsVerifier, JwtError};
|
||||
use dialoguer::theme::ColorfulTheme;
|
||||
use dialoguer::Select;
|
||||
use kanidm_client::{ClientError, KanidmClient};
|
||||
|
@ -319,13 +319,36 @@ async fn process_auth_state(
|
|||
// Add our new one
|
||||
let (spn, tonk) = match client.get_token().await {
|
||||
Some(t) => {
|
||||
let tonk = match JwsUnverified::from_str(&t).and_then(|jwtu| {
|
||||
jwtu.validate_embeded()
|
||||
.map(|jws: Jws<UserAuthToken>| jws.into_inner())
|
||||
let jwsc = match JwsCompact::from_str(&t) {
|
||||
Ok(j) => j,
|
||||
Err(err) => {
|
||||
error!(?err, "Unable to parse token");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let jws_verifier = if let Some(pub_jwk) = jwsc.get_jwk_pubkey() {
|
||||
match JwsEs256Verifier::try_from(pub_jwk) {
|
||||
Ok(verifier) => verifier,
|
||||
Err(err) => {
|
||||
error!(?err, "Unable to configure jws verifier");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error!("Unable to access token public key");
|
||||
std::process::exit(1);
|
||||
};
|
||||
|
||||
let tonk = match jws_verifier.verify(&jwsc).and_then(|jws| {
|
||||
jws.from_json::<UserAuthToken>().map_err(|serde_err| {
|
||||
error!(?serde_err);
|
||||
JwtError::InvalidJwt
|
||||
})
|
||||
}) {
|
||||
Ok(uat) => uat,
|
||||
Err(e) => {
|
||||
error!("Unable to parse token - {:?}", e);
|
||||
Err(err) => {
|
||||
error!(?err, "Unable to verify token signature");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
@ -479,16 +502,35 @@ impl LogoutOpt {
|
|||
}
|
||||
|
||||
// Server acked the logout, lets proceed with the local cleanup now.
|
||||
let jwtu = match JwsUnverified::from_str(&token) {
|
||||
Ok(value) => value,
|
||||
Err(e) => {
|
||||
error!(?e, "Unable to parse token from str");
|
||||
|
||||
let jwsc = match JwsCompact::from_str(&token) {
|
||||
Ok(j) => j,
|
||||
Err(err) => {
|
||||
error!(?err, "Unable to parse token");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let uat: UserAuthToken = match jwtu.validate_embeded() {
|
||||
Ok(jwt) => jwt.into_inner(),
|
||||
let jws_verifier = if let Some(pub_jwk) = jwsc.get_jwk_pubkey() {
|
||||
match JwsEs256Verifier::try_from(pub_jwk) {
|
||||
Ok(verifier) => verifier,
|
||||
Err(err) => {
|
||||
error!(?err, "Unable to configure jws verifier");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error!("Unable to access token public key");
|
||||
std::process::exit(1);
|
||||
};
|
||||
|
||||
let uat = match jws_verifier.verify(&jwsc).and_then(|jws| {
|
||||
jws.from_json::<UserAuthToken>().map_err(|serde_err| {
|
||||
error!(?serde_err);
|
||||
JwtError::InvalidJwt
|
||||
})
|
||||
}) {
|
||||
Ok(uat) => uat,
|
||||
Err(e) => {
|
||||
error!(?e, "Unable to verify token signature, may be corrupt");
|
||||
std::process::exit(1);
|
||||
|
@ -532,20 +574,32 @@ impl SessionOpt {
|
|||
})
|
||||
.into_iter()
|
||||
.filter_map(|(u, t)| {
|
||||
let jwtu = JwsUnverified::from_str(&t)
|
||||
let jwsc = JwsCompact::from_str(&t)
|
||||
.map_err(|e| {
|
||||
error!(?e, "Unable to parse token from str");
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
jwtu.validate_embeded()
|
||||
let jws_verifier = jwsc.get_jwk_pubkey().and_then(|pub_jwk| {
|
||||
JwsEs256Verifier::try_from(pub_jwk)
|
||||
.map_err(|e| {
|
||||
error!(?e, "Unable to configure jws verifier");
|
||||
})
|
||||
.ok()
|
||||
})?;
|
||||
|
||||
jws_verifier
|
||||
.verify(&jwsc)
|
||||
.and_then(|jws| {
|
||||
jws.from_json::<UserAuthToken>().map_err(|serde_err| {
|
||||
error!(?serde_err);
|
||||
JwtError::InvalidJwt
|
||||
})
|
||||
})
|
||||
.map_err(|e| {
|
||||
error!(?e, "Unable to verify token signature, may be corrupt");
|
||||
})
|
||||
.map(|jwt| {
|
||||
let uat = jwt.into_inner();
|
||||
(u, (t, uat))
|
||||
})
|
||||
.map(|uat| (u, (t, uat)))
|
||||
.ok()
|
||||
})
|
||||
.collect()
|
||||
|
|
Loading…
Reference in a new issue