diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7c2c0909d..20fc0bdfb 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -53,3 +53,4 @@ jobs: uses: actions-rs/cargo@v1 with: command: audit + args: --ignore RUSTSEC-2020-0071 diff --git a/Cargo.lock b/Cargo.lock index a113a0bb9..0d0f9ba88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -187,19 +187,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] -name = "bitflags" -version = "1.3.2" +name = "base64ct" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] -name = "block-buffer" -version = "0.10.4" +name = "bitflags" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bollard" @@ -277,9 +274,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" dependencies = [ "iana-time-zone", + "js-sys", "num-integer", "num-traits", "serde", + "time 0.1.45", + "wasm-bindgen", "winapi", ] @@ -351,20 +351,27 @@ dependencies = [ ] [[package]] -name = "core-foundation-sys" -version = "0.8.4" +name = "const-oid" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" [[package]] -name = "cpufeatures" -version = "0.2.6" +name = "core-foundation" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ + "core-foundation-sys", "libc", ] +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + [[package]] name = "crunchy" version = "0.2.2" @@ -425,13 +432,24 @@ dependencies = [ "syn 2.0.13", ] +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "digest" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ - "block-buffer", + "const-oid", "crypto-common", ] @@ -487,6 +505,15 @@ dependencies = [ "synstructure", ] +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "ff" version = "0.6.0" @@ -504,7 +531,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3776aaf60a45037a9c3cabdd8542b38693acaa3e241ff957181b72579d29feb" dependencies = [ - "num-bigint", + "num-bigint 0.2.6", "num-integer", "num-traits", "proc-macro2", @@ -518,6 +545,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.1.0" @@ -644,10 +686,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", ] [[package]] @@ -784,16 +824,16 @@ dependencies = [ ] [[package]] -name = "hyper-rustls" -version = "0.23.2" +name = "hyper-tls" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ - "http", + "bytes", "hyper", - "rustls", + "native-tls", "tokio", - "tokio-rustls", + "tokio-native-tls", ] [[package]] @@ -854,6 +894,15 @@ dependencies = [ "serde", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "io-lifetimes" version = "1.0.10" @@ -898,11 +947,28 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonwebtoken" +version = "8.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" +dependencies = [ + "base64 0.21.0", + "pem", + "ring", + "serde", + "serde_json", + "simple_asn1", +] + [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin", +] [[package]] name = "libc" @@ -910,6 +976,12 @@ version = "0.2.141" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +[[package]] +name = "libm" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" + [[package]] name = "link-cplusplus" version = "1.0.8" @@ -1000,12 +1072,16 @@ dependencies = [ "anyhow", "async-trait", "axum", + "chrono", "clap", "futures", "hex", "hyper", - "oauth2", + "jsonwebtoken", "rand 0.7.3", + "rand 0.8.5", + "reqwest", + "rsa", "serde", "serde_json", "threshold_crypto", @@ -1031,6 +1107,24 @@ dependencies = [ "tokio", ] +[[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]] name = "nu-ansi-term" version = "0.46.0" @@ -1052,6 +1146,34 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2399c9463abc5f909349d8aa9ba080e0b88b3ce2885389b60b993f39b1a56905" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -1062,6 +1184,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -1069,6 +1202,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -1081,26 +1215,6 @@ dependencies = [ "libc", ] -[[package]] -name = "oauth2" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeaf26a72311c087f8c5ba617c96fac67a5c04f430e716ac8d8ab2de62e23368" -dependencies = [ - "base64 0.13.1", - "chrono", - "getrandom 0.2.8", - "http", - "rand 0.8.5", - "reqwest", - "serde", - "serde_json", - "serde_path_to_error", - "sha2", - "thiserror", - "url", -] - [[package]] name = "object" version = "0.30.3" @@ -1116,6 +1230,50 @@ version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +[[package]] +name = "openssl" +version = "0.10.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d2f106ab837a24e03672c59b1239669a0596406ff657c3c0835b6b7f0f35a33" +dependencies = [ + "bitflags", + "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.13", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a20eace9dc2d82904039cb76dcf50fb1a0bba071cfd1629720b5d6f1ddba0fa" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "overload" version = "0.1.1" @@ -1152,11 +1310,29 @@ checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "smallvec", "windows-sys 0.45.0", ] +[[package]] +name = "pem" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +dependencies = [ + "base64 0.13.1", +] + +[[package]] +name = "pem-rfc7468" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.2.0" @@ -1195,6 +1371,34 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff33bdbdfc54cc98a2eca766ebdec3e1b8fb7387523d5c9c9a2891da856f719" +dependencies = [ + "der", + "pkcs8", + "spki", + "zeroize", +] + +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + [[package]] name = "portpicker" version = "0.1.1" @@ -1317,6 +1521,15 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + [[package]] name = "regex" version = "1.7.3" @@ -1356,27 +1569,25 @@ dependencies = [ "http", "http-body", "hyper", - "hyper-rustls", + "hyper-tls", "ipnet", "js-sys", "log", "mime", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", - "rustls", - "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", - "tokio-rustls", + "tokio-native-tls", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", "winreg", ] @@ -1395,6 +1606,26 @@ dependencies = [ "winapi", ] +[[package]] +name = "rsa" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55a77d189da1fee555ad95b7e50e7457d91c0e089ec68ca69ad2989413bbdab4" +dependencies = [ + "byteorder", + "digest", + "num-bigint-dig", + "num-integer", + "num-iter", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature", + "subtle", + "zeroize", +] + [[package]] name = "rustc-demangle" version = "0.1.22" @@ -1415,27 +1646,6 @@ dependencies = [ "windows-sys 0.45.0", ] -[[package]] -name = "rustls" -version = "0.20.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" -dependencies = [ - "log", - "ring", - "sct", - "webpki", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" -dependencies = [ - "base64 0.21.0", -] - [[package]] name = "rustversion" version = "1.0.12" @@ -1448,6 +1658,15 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "schannel" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +dependencies = [ + "windows-sys 0.42.0", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -1461,13 +1680,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" [[package]] -name = "sct" -version = "0.7.0" +name = "security-framework" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ - "ring", - "untrusted", + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" +dependencies = [ + "core-foundation-sys", + "libc", ] [[package]] @@ -1545,18 +1777,7 @@ dependencies = [ "indexmap", "serde", "serde_json", - "time", -] - -[[package]] -name = "sha2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", + "time 0.3.20", ] [[package]] @@ -1577,6 +1798,28 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + +[[package]] +name = "simple_asn1" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +dependencies = [ + "num-bigint 0.4.3", + "num-traits", + "thiserror", + "time 0.3.20", +] + [[package]] name = "slab" version = "0.4.8" @@ -1608,12 +1851,28 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + [[package]] name = "syn" version = "1.0.109" @@ -1654,6 +1913,19 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "tempfile" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall 0.3.5", + "rustix", + "windows-sys 0.45.0", +] + [[package]] name = "termcolor" version = "1.2.0" @@ -1713,6 +1985,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + [[package]] name = "time" version = "0.3.20" @@ -1795,14 +2078,13 @@ dependencies = [ ] [[package]] -name = "tokio-rustls" -version = "0.23.4" +name = "tokio-native-tls" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ - "rustls", + "native-tls", "tokio", - "webpki", ] [[package]] @@ -1970,7 +2252,6 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", - "serde", ] [[package]] @@ -1985,6 +2266,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.4" @@ -2007,6 +2294,12 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -2089,25 +2382,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki", -] - [[package]] name = "winapi" version = "0.3.9" @@ -2148,6 +2422,21 @@ dependencies = [ "windows-targets 0.48.0", ] +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-sys" version = "0.45.0" diff --git a/README.md b/README.md index 2531bb01a..56cab5495 100644 --- a/README.md +++ b/README.md @@ -34,4 +34,14 @@ Endpoint 2: Recover Account URL: /recover_account Request parameters: access_token, public_key - Response: status \ No newline at end of file + Response: status + +## OIDC (OAuth 2.0) authentication +We are using OpenID Connect (OIDC) standard to authenticate users (built on top of OAuth 2.0). +Check OIDC standard docs [here](https://openid.net/specs/openid-connect-core-1_0.html#IDToken) and Google OIDC docs [here](https://developers.google.com/identity/protocols/oauth2/openid-connect) + +### Client integration +There are several ways to get and use the ID token. The flow that we are using is called the "server" flow, you can find more info [here](https://developers.google.com/identity/openid-connect/openid-connect#authenticatingtheuser). The system will be able to process any token that is following the core OpenID Connect standard. In order to recieve the ID token from OpenID provider you will need to include the `openid` scope value to the Authorization Request. + +### Server integration +Internally, we are identifiying users by their issuer id (iss) and their unique ID (sub) retrieved form the ID token and separated by a colon: `:`. It means that each recovery method (like GitHub abd Google) is separated from one another even if they have the same email. \ No newline at end of file diff --git a/mpc-recovery/Cargo.toml b/mpc-recovery/Cargo.toml index ced2728a3..5201ff08c 100644 --- a/mpc-recovery/Cargo.toml +++ b/mpc-recovery/Cargo.toml @@ -27,9 +27,13 @@ hyper = { version = "0.14", features = ["full"] } actix-rt = "2.8" threshold_crypto = "0.4.0" rand = "0.7" +rand8 = { package = "rand", version = "0.8" } serde = "1" serde_json = "1" tokio = { version = "1.0", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } -oauth2 = "4.3.0" \ No newline at end of file +reqwest = "0.11.16" +jsonwebtoken = "8.3.0" +rsa = "0.8.2" +chrono = "0.4.24" diff --git a/mpc-recovery/src/leader_node/mod.rs b/mpc-recovery/src/leader_node/mod.rs index d171fd83d..3ebf939d0 100644 --- a/mpc-recovery/src/leader_node/mod.rs +++ b/mpc-recovery/src/leader_node/mod.rs @@ -68,11 +68,11 @@ async fn submit( // TODO: extract access token from payload let access_token = "validToken"; match T::verify_token(access_token).await { - Some(_) => { + Ok(_) => { tracing::info!("access token is valid"); // continue execution } - None => { + Err(_) => { tracing::error!("access token verification failed"); return (StatusCode::UNAUTHORIZED, Json(LeaderResponse::Err)); } diff --git a/mpc-recovery/src/oauth.rs b/mpc-recovery/src/oauth.rs index d638a417e..7cdda7e23 100644 --- a/mpc-recovery/src/oauth.rs +++ b/mpc-recovery/src/oauth.rs @@ -1,6 +1,29 @@ +use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation}; +use serde::{Deserialize, Serialize}; + #[async_trait::async_trait] pub trait OAuthTokenVerifier { - async fn verify_token(token: &str) -> Option<&str>; + async fn verify_token(token: &str) -> Result; // TODO: replace String error with custom error type + + /// This function validates JWT (OIDC ID token) by checking the signature received + /// from the issuer, issuer, audience, and expiration time. + fn validate_jwt( + token: &str, + public_key: &[u8], + issuer: &str, + audience: &str, + ) -> Result { + let mut validation = Validation::new(Algorithm::RS256); + validation.set_issuer(&[issuer]); + validation.set_audience(&[audience]); + + let decoding_key = DecodingKey::from_rsa_der(public_key); + + match decode::(token, &decoding_key, &validation) { + Ok(token_data) => Ok(token_data.claims), + Err(e) => Err(format!("Failed to validate the token: {}", e)), + } + } } pub enum SupportedTokenVerifiers { @@ -13,7 +36,7 @@ pub struct UniversalTokenVerifier {} #[async_trait::async_trait] impl OAuthTokenVerifier for UniversalTokenVerifier { - async fn verify_token(token: &str) -> Option<&str> { + async fn verify_token(token: &str) -> Result { // TODO: here we assume that verifier type can be determined from the token match get_token_verifier_type(token) { SupportedTokenVerifiers::GoogleTokenVerifier => { @@ -45,18 +68,20 @@ pub struct GoogleTokenVerifier {} #[async_trait::async_trait] impl OAuthTokenVerifier for GoogleTokenVerifier { - // TODO: replace with real implementation - async fn verify_token(token: &str) -> Option<&str> { - match token { - "validToken" => { - tracing::info!("GoogleTokenVerifier: access token is valid"); - Some("testAccountId") - } - _ => { - tracing::info!("GoogleTokenVerifier: access token verification failed"); - None - } - } + // Google specs for ID token verification: https://developers.google.com/identity/openid-connect/openid-connect#validatinganidtoken + async fn verify_token(token: &str) -> Result { + // TODO: Extract the public key of the authorization server from the OpenID Connect discovery endpoint or other configuration sources. Link: https://accounts.google.com/.well-known/openid-configuration + // TODO: get certs from response (jwks_uri) + let public_key = Vec::::new(); + + const GOOGLE_ISSUER_ID: &str = "https://accounts.google.com"; // TODO: should be an array, google provides two options + const GOOGLE_AUDIENCE_ID: &str = "TODO: get audience id from Google (register new project)"; + + let claims = Self::validate_jwt(token, &public_key, GOOGLE_ISSUER_ID, GOOGLE_AUDIENCE_ID) + .expect("Failed to validate JWT"); + let internal_user_identifier = format!("{}:{}", claims.iss, claims.sub); + + Ok(internal_user_identifier) } } @@ -65,51 +90,150 @@ pub struct TestTokenVerifier {} #[async_trait::async_trait] impl OAuthTokenVerifier for TestTokenVerifier { - async fn verify_token(token: &str) -> Option<&str> { + async fn verify_token(token: &str) -> Result { match token { "validToken" => { - tracing::info!("TestTokenVerifier: access token is valid"); - Some("testAccountId") + tracing::info!(target: "test-token-verifier", "access token is valid"); + Ok("testAccountId".to_string()) } _ => { - tracing::info!("TestTokenVerifier: access token verification failed"); - None + tracing::info!(target: "test-token-verifier", "access token verification failed"); + Err("Invalid token".to_string()) } } } } -#[tokio::test] -async fn test_verify_token_valid() { - let token = "validToken"; - let account_id = TestTokenVerifier::verify_token(token).await.unwrap(); - assert_eq!(account_id, "testAccountId"); +#[derive(Debug, Serialize, Deserialize)] +pub struct IdTokenClaims { + iss: String, + sub: String, + aud: String, + exp: usize, } -#[tokio::test] -async fn test_verify_token_invalid_with_test_verifier() { - let token = "invalid"; - let account_id = TestTokenVerifier::verify_token(token).await; - assert_eq!(account_id, None); -} +#[cfg(test)] +mod tests { + use super::*; + use chrono::{Duration, Utc}; + use jsonwebtoken::{encode, EncodingKey, Header}; + use rand8::rngs::OsRng; + use rsa::{ + pkcs1::{EncodeRsaPrivateKey, EncodeRsaPublicKey}, + RsaPrivateKey, RsaPublicKey, + }; -#[tokio::test] -async fn test_verify_token_valid_with_test_verifier() { - let token = "validToken"; - let account_id = TestTokenVerifier::verify_token(token).await.unwrap(); - assert_eq!(account_id, "testAccountId"); -} + #[test] + fn test_validate_jwt() { + let (private_key_der, public_key_der): (Vec, Vec) = get_rsa_der_key_pair(); -#[tokio::test] -async fn test_verify_token_invalid_with_universal_verifier() { - let token = "invalid"; - let account_id = UniversalTokenVerifier::verify_token(token).await; - assert_eq!(account_id, None); -} + let my_claims = IdTokenClaims { + iss: "test_issuer".to_string(), + sub: "test_subject".to_string(), + aud: "test_audience".to_string(), + exp: (Utc::now() + Duration::hours(1)).timestamp() as usize, + }; + + let token = match encode( + &Header::new(Algorithm::RS256), + &my_claims, + &EncodingKey::from_rsa_der(&private_key_der), + ) { + Ok(t) => t, + Err(e) => panic!("Failed to encode token: {}", e), + }; + + // Valid token and claims + GoogleTokenVerifier::validate_jwt(&token, &public_key_der, &my_claims.iss, &my_claims.aud) + .unwrap(); -#[tokio::test] -async fn test_verify_token_valid_with_universal_verifier() { - let token = "validToken"; - let account_id = UniversalTokenVerifier::verify_token(token).await.unwrap(); - assert_eq!(account_id, "testAccountId"); + // Invalid public key + let (invalid_public_key, _invalid_private_key) = get_rsa_der_key_pair(); + match GoogleTokenVerifier::validate_jwt( + &token, + &invalid_public_key, + &my_claims.iss, + &my_claims.aud, + ) { + Ok(_) => panic!("Token validation should fail"), + Err(e) => assert_eq!(e, "Failed to validate the token: InvalidSignature"), + } + + // Invalid issuer + match GoogleTokenVerifier::validate_jwt( + &token, + &public_key_der, + "invalid_issuer", + &my_claims.aud, + ) { + Ok(_) => panic!("Token validation should fail"), + Err(e) => assert_eq!(e, "Failed to validate the token: InvalidIssuer"), + } + + // Invalid audience + match GoogleTokenVerifier::validate_jwt( + &token, + &public_key_der, + &my_claims.iss, + "invalid_audience", + ) { + Ok(_) => panic!("Token validation should fail"), + Err(e) => assert_eq!(e, "Failed to validate the token: InvalidAudience"), + } + } + + #[tokio::test] + async fn test_verify_token_valid() { + let token = "validToken"; + let account_id = TestTokenVerifier::verify_token(token).await.unwrap(); + assert_eq!(account_id, "testAccountId"); + } + + #[tokio::test] + async fn test_verify_token_invalid_with_test_verifier() { + let token = "invalid"; + let account_id = TestTokenVerifier::verify_token(token).await; + assert_eq!(account_id, Err("Invalid token".to_string())); + } + + #[tokio::test] + async fn test_verify_token_valid_with_test_verifier() { + let token = "validToken"; + let account_id = TestTokenVerifier::verify_token(token).await.unwrap(); + assert_eq!(account_id, "testAccountId"); + } + + #[tokio::test] + async fn test_verify_token_invalid_with_universal_verifier() { + let token = "invalid"; + let account_id = UniversalTokenVerifier::verify_token(token).await; + assert_eq!(account_id, Err("Invalid token".to_string())); + } + + #[tokio::test] + async fn test_verify_token_valid_with_universal_verifier() { + let token = "validToken"; + let account_id = UniversalTokenVerifier::verify_token(token).await.unwrap(); + assert_eq!(account_id, "testAccountId"); + } + + pub fn get_rsa_der_key_pair() -> (Vec, Vec) { + let mut rng = OsRng; + let bits: usize = 2048; + let private_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key"); + let public_key = RsaPublicKey::from(&private_key); + + let private_key_der = private_key + .to_pkcs1_der() + .expect("Failed to encode private key") + .as_bytes() + .to_vec(); + let public_key_der = public_key + .to_pkcs1_der() + .expect("Failed to encode public key") + .as_bytes() + .to_vec(); + + (private_key_der, public_key_der) + } } diff --git a/mpc-recovery/src/sign_node/mod.rs b/mpc-recovery/src/sign_node/mod.rs index 344e852db..eaebc5d12 100644 --- a/mpc-recovery/src/sign_node/mod.rs +++ b/mpc-recovery/src/sign_node/mod.rs @@ -44,7 +44,7 @@ async fn sign( // TODO: extract access token from payload let access_token = "validToken"; match T::verify_token(access_token).await { - Some(_) => { + Ok(_) => { tracing::debug!("access token is valid"); let response = SigShareResponse::Ok { node_id: state.id, @@ -52,7 +52,7 @@ async fn sign( }; (StatusCode::OK, Json(response)) } - None => { + Err(_) => { tracing::debug!("access token verification failed"); (StatusCode::UNAUTHORIZED, Json(SigShareResponse::Err)) }