From 2d0d6857ce34337c821565ee8804c559a6d2fb35 Mon Sep 17 00:00:00 2001 From: Philippe Loctaux Date: Sun, 12 Mar 2023 14:08:39 +0100 Subject: [PATCH] ezidam: added openid configration, well known route --- Cargo.lock | 516 ++++++++++++++++++++++++- crates/ezidam/Cargo.toml | 4 +- crates/ezidam/src/error/conversion.rs | 6 + crates/ezidam/src/routes.rs | 2 + crates/ezidam/src/routes/well_known.rs | 25 ++ crates/openid/Cargo.toml | 10 + crates/openid/src/error.rs | 11 + crates/openid/src/lib.rs | 6 + crates/openid/src/openid.rs | 66 ++++ crates/settings/src/lib.rs | 3 + 10 files changed, 647 insertions(+), 2 deletions(-) create mode 100644 crates/ezidam/src/routes/well_known.rs create mode 100644 crates/openid/Cargo.toml create mode 100644 crates/openid/src/error.rs create mode 100644 crates/openid/src/lib.rs create mode 100644 crates/openid/src/openid.rs diff --git a/Cargo.lock b/Cargo.lock index b382922..e655a40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -72,6 +72,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anyhow" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" + [[package]] name = "argon2" version = "0.4.1" @@ -151,6 +157,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base64" version = "0.13.1" @@ -267,6 +279,7 @@ dependencies = [ "js-sys", "num-integer", "num-traits", + "serde", "time 0.1.45", "wasm-bindgen", "winapi 0.3.9", @@ -320,6 +333,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "const-oid" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" + [[package]] name = "cookie" version = "0.16.2" @@ -436,6 +455,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -500,6 +531,41 @@ dependencies = [ "syn", ] +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "database" version = "0.0.0" @@ -515,6 +581,17 @@ dependencies = [ "sqlx", ] +[[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 = "deunicode" version = "0.4.3" @@ -561,6 +638,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer", + "const-oid", "crypto-common", "subtle", ] @@ -571,6 +649,24 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" +[[package]] +name = "dyn-clone" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" + +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + [[package]] name = "either" version = "1.8.1" @@ -580,6 +676,28 @@ dependencies = [ "serde", ] +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "digest", + "ff", + "generic-array", + "group", + "hkdf", + "pem-rfc7468", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "email_address" version = "0.2.4" @@ -639,7 +757,7 @@ checksum = "e8af5ef47e2ed89d23d0ecbc1b681b30390069de70260937877514377fc24feb" dependencies = [ "bit_field", "flume", - "half", + "half 2.2.1", "lebe", "miniz_oxide", "smallvec", @@ -657,6 +775,8 @@ dependencies = [ "id", "identicon-rs", "infer", + "jwt", + "openid", "rocket", "rocket_db_pools", "rocket_dyn_templates", @@ -674,6 +794,16 @@ dependencies = [ "instant", ] +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core", + "subtle", +] + [[package]] name = "figment" version = "0.10.8" @@ -946,6 +1076,17 @@ dependencies = [ "walkdir", ] +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + [[package]] name = "h2" version = "0.3.15" @@ -965,6 +1106,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + [[package]] name = "half" version = "2.2.1" @@ -1156,6 +1303,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "identicon-rs" version = "4.0.1" @@ -1326,6 +1479,40 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jwt" +version = "0.0.0" +dependencies = [ + "id", + "jwt-compact", + "rand", + "rsa", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "jwt-compact" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bcc576baa96136028d34d45ab5c840d146235a4c37c87d96237d05fea222194" +dependencies = [ + "anyhow", + "base64ct", + "chrono", + "hmac", + "rand_core", + "rsa", + "serde", + "serde_cbor", + "serde_json", + "sha2", + "smallvec", + "subtle", + "zeroize", +] + [[package]] name = "keccak" version = "0.1.3" @@ -1350,6 +1537,9 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "lazycell" @@ -1369,6 +1559,12 @@ version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +[[package]] +name = "libm" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" + [[package]] name = "libsqlite3-sys" version = "0.24.2" @@ -1631,6 +1827,23 @@ dependencies = [ "winapi 0.3.9", ] +[[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", + "smallvec", + "zeroize", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -1641,6 +1854,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-rational" version = "0.4.1" @@ -1659,6 +1883,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -1671,6 +1896,25 @@ 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", + "http", + "rand", + "serde", + "serde_json", + "serde_path_to_error", + "sha2", + "thiserror", + "url", +] + [[package]] name = "once_cell" version = "1.17.1" @@ -1683,12 +1927,84 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "openid" +version = "0.0.0" +dependencies = [ + "openidconnect", + "serde_json", + "thiserror", + "url", +] + +[[package]] +name = "openidconnect" +version = "3.0.0-alpha.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16592b0a6cd285efab91c419b60f771c425a1ae6316fda170be6d1781af36a38" +dependencies = [ + "base64 0.13.1", + "chrono", + "dyn-clone", + "hmac", + "http", + "itertools", + "log", + "oauth2", + "p256", + "p384", + "rand", + "rsa", + "serde", + "serde-value", + "serde_derive", + "serde_json", + "serde_path_to_error", + "serde_plain", + "serde_with", + "sha2", + "subtle", + "thiserror", + "url", +] + +[[package]] +name = "ordered-float" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" +dependencies = [ + "num-traits", +] + [[package]] name = "overload" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "p256" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" +dependencies = [ + "ecdsa", + "elliptic-curve", + "sha2", +] + +[[package]] +name = "p384" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" +dependencies = [ + "ecdsa", + "elliptic-curve", + "sha2", +] + [[package]] name = "parking_lot" version = "0.11.2" @@ -1786,6 +2102,15 @@ dependencies = [ "syn", ] +[[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" @@ -1907,6 +2232,28 @@ 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" @@ -2081,6 +2428,17 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint", + "hmac", + "zeroize", +] + [[package]] name = "ring" version = "0.16.20" @@ -2123,6 +2481,7 @@ dependencies = [ "rocket_codegen", "rocket_http", "serde", + "serde_json", "state", "tempfile", "time 0.3.20", @@ -2212,6 +2571,27 @@ dependencies = [ "uncased", ] +[[package]] +name = "rsa" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "094052d5470cbcef561cb848a7209968c9f12dfa6d668f4bca048ac5de51099c" +dependencies = [ + "byteorder", + "digest", + "num-bigint-dig", + "num-integer", + "num-iter", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "signature", + "smallvec", + "subtle", + "zeroize", +] + [[package]] name = "rustix" version = "0.36.8" @@ -2294,6 +2674,20 @@ dependencies = [ "untrusted", ] +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "serde" version = "1.0.152" @@ -2303,6 +2697,26 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half 1.8.2", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.152" @@ -2325,6 +2739,46 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db0969fff533976baadd92e08b1d102c5a3d8a8049eadfd69d4d1e3c5b2ed189" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_plain" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6018081315db179d0ce57b1fe4b62a12a0028c9cf9bbef868c9cf477b3c34ae" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_with" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +dependencies = [ + "serde", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "settings" version = "0.0.0" @@ -2375,6 +2829,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "simd-adler32" version = "0.3.4" @@ -2436,6 +2900,16 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "sqlformat" version = "0.1.8" @@ -2565,6 +3039,12 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "subtle" version = "2.4.1" @@ -2582,6 +3062,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + [[package]] name = "tempfile" version = "3.4.0" @@ -3029,6 +3521,7 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -3332,6 +3825,27 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "zeroize" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zune-inflate" version = "0.2.51" diff --git a/crates/ezidam/Cargo.toml b/crates/ezidam/Cargo.toml index 92a8fdd..e01f889 100644 --- a/crates/ezidam/Cargo.toml +++ b/crates/ezidam/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -rocket = "0.5.0-rc.2" +rocket = { version = "0.5.0-rc.2", features = ["json"] } rocket_db_pools = { version = "0.1.0-rc.2", features = ["sqlx_sqlite"] } rocket_dyn_templates = { version = "0.1.0-rc.2", features = ["tera"] } infer = { version = "0.12.0", default-features = false } @@ -18,3 +18,5 @@ settings = { path = "../settings" } users = { path = "../users" } id = { path = "../id" } hash = { path = "../hash" } +openid = { path = "../openid" } +jwt = { path = "../jwt" } diff --git a/crates/ezidam/src/error/conversion.rs b/crates/ezidam/src/error/conversion.rs index feccae0..277df79 100644 --- a/crates/ezidam/src/error/conversion.rs +++ b/crates/ezidam/src/error/conversion.rs @@ -29,3 +29,9 @@ impl From for Error { Error::internal_server_error(e) } } + +impl From for Error { + fn from(e: openid::Error) -> Self { + Error::internal_server_error(e) + } +} diff --git a/crates/ezidam/src/routes.rs b/crates/ezidam/src/routes.rs index 336f1c6..9bd5d9d 100644 --- a/crates/ezidam/src/routes.rs +++ b/crates/ezidam/src/routes.rs @@ -3,6 +3,7 @@ use rocket::{Build, Rocket}; pub mod auth; pub mod root; pub mod setup; +pub mod well_known; pub(self) mod prelude { pub use crate::database::Database; @@ -34,4 +35,5 @@ pub fn routes(rocket_builder: Rocket) -> Rocket { // Setup .mount("/setup", setup::routes()) .mount("/auth", auth::routes()) + .mount("/.well-known", well_known::routes()) } diff --git a/crates/ezidam/src/routes/well_known.rs b/crates/ezidam/src/routes/well_known.rs new file mode 100644 index 0000000..ce8c20d --- /dev/null +++ b/crates/ezidam/src/routes/well_known.rs @@ -0,0 +1,25 @@ +use super::prelude::*; +use rocket::get; +use rocket::serde::json::{Json, Value}; +use settings::Settings; + +pub fn routes() -> Vec { + routes![openid_configuration] +} + +#[get("/openid-configuration")] +async fn openid_configuration(mut db: Connection) -> Result> { + // Get settings + let settings = Settings::get(&mut *db).await?; + + // Get server url + let url = settings + .url() + .ok_or_else(|| Error::not_found("Server url"))?; + + // Create openid configuration + let openid_configuration = openid::configuration(url)?; + + // HTTP response + Ok(Json(openid_configuration)) +} diff --git a/crates/openid/Cargo.toml b/crates/openid/Cargo.toml new file mode 100644 index 0000000..5a1fbba --- /dev/null +++ b/crates/openid/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "openid" +version = "0.0.0" +edition = "2021" + +[dependencies] +thiserror = { workspace = true } +url = { workspace = true } +serde_json = { workspace = true } +openidconnect = { version = "3.0.0-alpha.1", default-features = false } diff --git a/crates/openid/src/error.rs b/crates/openid/src/error.rs new file mode 100644 index 0000000..8f35e2b --- /dev/null +++ b/crates/openid/src/error.rs @@ -0,0 +1,11 @@ +// error +#[derive(thiserror::Error)] +// the rest +#[derive(Debug)] +pub enum Error { + #[error("Failed to parse an URL: `{0}`")] + UrlParse(#[from] url::ParseError), + + #[error("Failed to serialize to JSON: `{0}`")] + JsonSerialization(#[from] serde_json::Error), +} diff --git a/crates/openid/src/lib.rs b/crates/openid/src/lib.rs new file mode 100644 index 0000000..b0aed67 --- /dev/null +++ b/crates/openid/src/lib.rs @@ -0,0 +1,6 @@ +mod error; +mod openid; + +/// Exports +pub use error::Error; +pub use openid::configuration; diff --git a/crates/openid/src/openid.rs b/crates/openid/src/openid.rs new file mode 100644 index 0000000..326b68c --- /dev/null +++ b/crates/openid/src/openid.rs @@ -0,0 +1,66 @@ +use crate::error::Error; +use openidconnect::core::{ + CoreClaimName, CoreJwsSigningAlgorithm, CoreProviderMetadata, CoreResponseType, + CoreSubjectIdentifierType, +}; +use openidconnect::{ + AuthUrl, EmptyAdditionalProviderMetadata, IssuerUrl, JsonWebKeySetUrl, ResponseTypes, Scope, + TokenUrl, UserInfoUrl, +}; +use serde_json::Value; +use url::Url; + +pub fn configuration(base_url: &str) -> Result { + let base_url = Url::parse(base_url)?; + + let authorization_endpoint = base_url.join("/oauth/authorize")?; + let jwks_uri = base_url.join("/.well-known/jwks.json")?; + let token_url = base_url.join("/oauth/token")?; + let user_info_url = base_url.join("/oauth/userinfo")?; + + let provider_metadata = CoreProviderMetadata::new( + // Parameters required by the OpenID Connect Discovery spec. + IssuerUrl::from_url(base_url), + AuthUrl::from_url(authorization_endpoint), + // Use the JsonWebKeySet struct to serve the JWK Set at this URL. + JsonWebKeySetUrl::from_url(jwks_uri), + // Supported response types (flows). + vec![ + // Recommended: support the code flow. + ResponseTypes::new(vec![CoreResponseType::Code]), + // Optional: support the implicit flow. + ResponseTypes::new(vec![CoreResponseType::Token, CoreResponseType::IdToken]), // Other flows including hybrid flows may also be specified here. + ], + // For user privacy, the Pairwise subject identifier type is preferred. This prevents + // distinct relying parties (clients) from knowing whether their users represent the same + // real identities. This identifier type is only useful for relying parties that don't + // receive the 'email', 'profile' or other personally-identifying scopes. + // The Public subject identifier type is also supported. + vec![CoreSubjectIdentifierType::Pairwise], + vec![CoreJwsSigningAlgorithm::RsaSsaPssSha256], + // OpenID Connect Providers may supply custom metadata by providing a struct that + // implements the AdditionalProviderMetadata trait. This requires manually using the + // generic ProviderMetadata struct rather than the CoreProviderMetadata type alias, + // however. + EmptyAdditionalProviderMetadata {}, + ) + // Specify the token endpoint (required for the code flow). + .set_token_endpoint(Some(TokenUrl::from_url(token_url))) + // Recommended: support the UserInfo endpoint. + .set_userinfo_endpoint(Some(UserInfoUrl::from_url(user_info_url))) + // Recommended: specify the supported scopes. + .set_scopes_supported(Some(vec![Scope::new("openid".to_string())])) + // Recommended: specify the supported ID token claims. + .set_claims_supported(Some(vec![ + // Providers may also define an enum instead of using CoreClaimName. + CoreClaimName::new("sub".to_string()), + CoreClaimName::new("aud".to_string()), + CoreClaimName::new("email".to_string()), + CoreClaimName::new("exp".to_string()), + CoreClaimName::new("iat".to_string()), + CoreClaimName::new("iss".to_string()), + CoreClaimName::new("name".to_string()), + ])); + + Ok(serde_json::to_value(provider_metadata)?) +} diff --git a/crates/settings/src/lib.rs b/crates/settings/src/lib.rs index 6147db9..e55cc96 100644 --- a/crates/settings/src/lib.rs +++ b/crates/settings/src/lib.rs @@ -23,4 +23,7 @@ impl Settings { pub fn business_name(&self) -> &str { &self.business_name } + pub fn url(&self) -> Option<&str> { + self.url.as_deref() + } }