diff options
author | Kjetil Orbekk <kj@orbekk.com> | 2022-10-07 16:59:29 -0400 |
---|---|---|
committer | Kjetil Orbekk <kj@orbekk.com> | 2022-10-07 16:59:29 -0400 |
commit | c64a7a640ac8c59eb6339f0a06d2ad2efab3fd11 (patch) | |
tree | 229ccf88da26d5339aadab98013834b6c2af6cbc | |
parent | 01753ebd32e4e0fa8adb11fb02a77720773e3018 (diff) |
Start working on authentication
-rw-r--r-- | Cargo.lock | 622 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | data/src/lib.rs | 6 | ||||
-rw-r--r-- | protocol/Cargo.toml (renamed from data/Cargo.toml) | 2 | ||||
-rw-r--r-- | protocol/src/lib.rs | 6 | ||||
-rw-r--r-- | server/.env | 7 | ||||
-rw-r--r-- | server/Cargo.toml | 7 | ||||
-rw-r--r-- | server/src/auth.rs | 97 | ||||
-rw-r--r-- | server/src/main.rs | 79 | ||||
-rw-r--r-- | webapp/Cargo.toml | 2 | ||||
-rw-r--r-- | webapp/src/components.rs | 2 | ||||
-rw-r--r-- | webapp/src/components/app_context_provider.rs | 50 | ||||
-rw-r--r-- | webapp/src/main.rs | 60 |
13 files changed, 879 insertions, 63 deletions
@@ -9,6 +9,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] name = "aho-corasick" version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -33,6 +44,15 @@ dependencies = [ ] [[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] name = "anyhow" version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -87,7 +107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2628a243073c55aef15a1c1fe45c87f21b84f9e89ca9e7b262a180d3d03543d" dependencies = [ "async-trait", - "axum-core", + "axum-core 0.3.0-rc.2", "bitflags", "bytes", "futures-util", @@ -113,6 +133,22 @@ dependencies = [ [[package]] name = "axum-core" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f0c0a60006f2a293d82d571f635042a72edf927539b7685bd62d361963839b" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" version = "0.3.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "473bd0762170028bb6b5068be9e97de2a9f0af3bf2084498d840498f47194d3d" @@ -140,6 +176,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + +[[package]] name = "boolinator" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -173,12 +218,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] name = "bytes" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -191,6 +248,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] +name = "chrono" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" +dependencies = [ + "iana-time-zone", + "num-integer", + "num-traits", + "serde", + "winapi", +] + +[[package]] name = "console_error_panic_hook" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -201,6 +271,32 @@ dependencies = [ ] [[package]] +name = "cookie" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "344adc371239ef32293cb1c4fe519592fcf21206c79c02854320afcdf3ab4917" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] name = "crc32fast" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -210,11 +306,23 @@ dependencies = [ ] [[package]] -name = "data" -version = "0.1.0" +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "serde", - "serde_json", + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" +dependencies = [ + "block-buffer", + "crypto-common", ] [[package]] @@ -224,6 +332,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" [[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + +[[package]] +name = "encoding_rs" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] name = "env_logger" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -277,6 +400,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" [[package]] +name = "futures-io" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" + +[[package]] +name = "futures-macro" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "futures-sink" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -295,13 +435,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" dependencies = [ "futures-core", + "futures-io", + "futures-macro", "futures-task", + "memchr", "pin-project-lite", "pin-utils", "slab", ] [[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] name = "getrandom" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -447,10 +600,42 @@ dependencies = [ ] [[package]] +name = "h2" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hdrhistogram" +version = "7.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f19b9f54f7c7f55e31401bb647626ce0cf0f67b0004982ce815b3ee72a02aa8" +dependencies = [ + "byteorder", + "num-traits", +] [[package]] name = "heck" @@ -523,6 +708,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", + "h2", "http", "http-body", "httparse", @@ -537,6 +723,42 @@ dependencies = [ ] [[package]] +name = "hyper-rustls" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" +dependencies = [ + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd911b35d940d2bd0bea0f9100068e5b97b51a1cbe13d13382f132e0365257a0" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] name = "indexmap" version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -547,6 +769,12 @@ dependencies = [ ] [[package]] +name = "ipnet" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" + +[[package]] name = "iri-string" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -556,6 +784,15 @@ dependencies = [ ] [[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] name = "itoa" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -602,6 +839,15 @@ dependencies = [ ] [[package]] +name = "lru" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6e8aaa3f231bb4bd57b84b2d5dc3ae7f350265df8aa96492e0bc394a1571909" +dependencies = [ + "hashbrown", +] + +[[package]] name = "matchers" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -692,6 +938,36 @@ dependencies = [ ] [[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-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] name = "num_cpus" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -702,12 +978,74 @@ dependencies = [ ] [[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + +[[package]] +name = "oauth2" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d62c436394991641b970a92e23e8eeb4eb9bca74af4f5badc53bcd568daadbd" +dependencies = [ + "base64", + "chrono", + "getrandom", + "http", + "rand", + "reqwest", + "serde", + "serde_json", + "serde_path_to_error", + "sha2", + "thiserror", + "url", +] + +[[package]] name = "once_cell" version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" [[package]] +name = "openidconnect" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e26afc60b2bf11b9a039db1f3a3c0d5fe201eebdbe646a8ecb8342c8240e3271" +dependencies = [ + "base64", + "chrono", + "http", + "itertools", + "log", + "num-bigint", + "oauth2", + "rand", + "ring", + "serde", + "serde-value", + "serde_derive", + "serde_json", + "serde_path_to_error", + "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" @@ -814,6 +1152,14 @@ dependencies = [ ] [[package]] +name = "protocol" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] name = "quote" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -888,12 +1234,87 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] +name = "reqwest" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] name = "route-recognizer" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" [[package]] +name = "rustls" +version = "0.20.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" +dependencies = [ + "base64", +] + +[[package]] name = "rustversion" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -918,6 +1339,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] name = "serde" version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -927,6 +1358,16 @@ dependencies = [ ] [[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-wasm-bindgen" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -961,6 +1402,15 @@ dependencies = [ ] [[package]] +name = "serde_path_to_error" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "184c643044780f7ceb59104cef98a5a6f12cb2288a7bc701ab93a362b49fd47d" +dependencies = [ + "serde", +] + +[[package]] name = "serde_urlencoded" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -977,14 +1427,30 @@ name = "server" version = "0.1.0" dependencies = [ "axum", - "data", "dotenv", + "lru", + "openidconnect", + "protocol", "serde", "serde_json", "tokio", + "tower", + "tower-cookies", "tower-http", "tracing", "tracing-subscriber", + "uuid", +] + +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest", ] [[package]] @@ -1031,6 +1497,12 @@ dependencies = [ ] [[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] name = "strum" version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1105,6 +1577,39 @@ dependencies = [ ] [[package]] +name = "time" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d634a985c4d4238ec39cacaed2e7ae552fbd3c476b552c1deac3021b7d7eaf0c" +dependencies = [ + "itoa", + "libc", + "num_threads", + "time-macros", +] + +[[package]] +name = "time-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] name = "tokio" version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1136,6 +1641,17 @@ dependencies = [ ] [[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls", + "tokio", + "webpki", +] + +[[package]] name = "tokio-util" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1146,6 +1662,7 @@ dependencies = [ "futures-sink", "pin-project-lite", "tokio", + "tracing", ] [[package]] @@ -1156,15 +1673,37 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", + "hdrhistogram", + "indexmap", "pin-project", "pin-project-lite", + "rand", + "slab", "tokio", + "tokio-util", "tower-layer", "tower-service", "tracing", ] [[package]] +name = "tower-cookies" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19833e336396f3953e5ab1513d72b5e5ea51d5ad39b78d306766a05740b48b97" +dependencies = [ + "async-trait", + "axum-core 0.2.8", + "cookie", + "futures-util", + "http", + "parking_lot", + "pin-project-lite", + "tower-layer", + "tower-service", +] + +[[package]] name = "tower-http" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1276,6 +1815,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] name = "unicase" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1285,18 +1830,53 @@ dependencies = [ ] [[package]] +name = "unicode-bidi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] name = "unicode-ident" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" [[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] name = "uuid" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f" dependencies = [ "getrandom", + "rand", + "serde", ] [[package]] @@ -1422,13 +2002,13 @@ version = "0.1.0" dependencies = [ "anyhow", "console_error_panic_hook", - "data", "dotenv", "env_logger", "getrandom", "gloo-net", "lazy_static", "log", + "protocol", "rand", "regex", "strum", @@ -1441,6 +2021,25 @@ dependencies = [ ] [[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be" +dependencies = [ + "webpki", +] + +[[package]] name = "wee_alloc" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1527,6 +2126,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" [[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + +[[package]] name = "yew" version = "0.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1,6 +1,6 @@ [workspace] members = [ - "data", + "protocol", "server", "webapp", ] diff --git a/data/src/lib.rs b/data/src/lib.rs deleted file mode 100644 index 7a11e59..0000000 --- a/data/src/lib.rs +++ /dev/null @@ -1,6 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize)] -pub struct MyMessage { - pub message: String, -} diff --git a/data/Cargo.toml b/protocol/Cargo.toml index 58c5ba3..2836fad 100644 --- a/data/Cargo.toml +++ b/protocol/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "data" +name = "protocol" version = "0.1.0" edition = "2021" diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs new file mode 100644 index 0000000..a56554f --- /dev/null +++ b/protocol/src/lib.rs @@ -0,0 +1,6 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] +pub struct UserInfo { + pub username: String, +} diff --git a/server/.env b/server/.env index 720d4c7..a639376 100644 --- a/server/.env +++ b/server/.env @@ -1,4 +1,7 @@ RUST_LOG=info,tower_http=trace BIND_ADDRESS=[::]:11121 -WEBAPP_PATH=../webapp/dist/ -RUST_BACKTRACE=1
\ No newline at end of file +RUST_BACKTRACE=1 +OPENID_ISSUER_URL=https://auth.orbekk.com/realms/test +OPENID_CLIENT_ID=test-client +OPENID_CLIENT_SECRET=EbIMIpGnYPrG1GBl6eZtVM5zIhiuu5p1 +APP_URL=https://bridge.orbekk.com
\ No newline at end of file diff --git a/server/Cargo.toml b/server/Cargo.toml index 88dee76..f25aa4c 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -14,4 +14,9 @@ tokio = { version = "1.21.2", features = ["full"] } tower-http = { version = "0.3.4", features = ["full"] } tracing = "0.1.37" tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } -data = { path = "../data" } +protocol = { path = "../protocol" } +openidconnect = "2.3.2" +lru = "0.8.1" +uuid = { version = "1.1.2", features = ["serde", "fast-rng", "v4"] } +tower-cookies = "0.7.0" +tower = { version = "0.4.13", features = ["full"] } diff --git a/server/src/auth.rs b/server/src/auth.rs new file mode 100644 index 0000000..ab1ba8b --- /dev/null +++ b/server/src/auth.rs @@ -0,0 +1,97 @@ +use std::{ + env, + num::NonZeroUsize, + sync::{Arc, Mutex}, +}; + +use lru::LruCache; +use openidconnect::{ + core::{CoreClient, CoreProviderMetadata, CoreResponseType}, + reqwest::async_http_client, + url::Url, + AccessTokenHash, AuthenticationFlow, AuthorizationCode, ClientId, ClientSecret, CsrfToken, + IssuerUrl, Nonce, OAuth2TokenResponse, PkceCodeChallenge, RedirectUrl, Scope, TokenResponse, +}; +use uuid::Uuid; +use serde::{Deserialize, Serialize}; + +pub struct LoginState { + csrf_token: CsrfToken, + nonce: Nonce, +} + +pub struct Authenticator { + pub client: CoreClient, + pub login_cache: Arc<Mutex<LruCache<EndUserId, LoginState>>>, +} + +#[derive(Eq, PartialEq, Hash, Debug, Clone, Serialize, Deserialize)] +pub struct EndUserId(Uuid); + +impl EndUserId { + pub fn new() -> Self { + Self(Uuid::new_v4()) + } +} + +const LOGIN_CACHE_SIZE: usize = 50; + +pub const LOGIN_CALLBACK: &'static str = "/api/login_callback"; +fn redirect_url(app_url: &str) -> RedirectUrl { + RedirectUrl::new(format!("{}{}", app_url, LOGIN_CALLBACK)).unwrap() +} + +impl Authenticator { + pub async fn new( + issuer_url: IssuerUrl, + client_id: ClientId, + client_secret: ClientSecret, + redirect_uri: RedirectUrl, + ) -> Self { + // Use OpenID Connect Discovery to fetch the provider metadata. + let provider_metadata = CoreProviderMetadata::discover_async(issuer_url, async_http_client) + .await + .unwrap(); + + let client = + CoreClient::from_provider_metadata(provider_metadata, client_id, Some(client_secret)) + // Set the URL the user will be redirected to after the authorization process. + .set_redirect_uri(redirect_uri); + + Self { + client, + login_cache: Arc::new(Mutex::new(LruCache::new( + NonZeroUsize::new(LOGIN_CACHE_SIZE).unwrap(), + ))), + } + } + + pub async fn from_env() -> Self { + let app_url = env::var("APP_URL").unwrap(); + Authenticator::new( + IssuerUrl::new(env::var("OPENID_ISSUER_URL").unwrap()).unwrap(), + ClientId::new(env::var("OPENID_CLIENT_ID").unwrap()), + ClientSecret::new(env::var("OPENID_CLIENT_SECRET").unwrap()), + redirect_url(&app_url), + ) + .await + } + + pub async fn get_login_url(&self) -> (EndUserId, Url) { + let (auth_url, csrf_token, nonce) = self + .client + .authorize_url( + AuthenticationFlow::<CoreResponseType>::AuthorizationCode, + CsrfToken::new_random, + Nonce::new_random, + ) + .add_scope(Scope::new("email".to_string())) + .add_scope(Scope::new("profile".to_string())) + .url(); + let user_id = EndUserId::new(); + self.login_cache + .lock().unwrap() + .put(user_id.clone(), LoginState { csrf_token, nonce }); + (user_id, auth_url) + } +} diff --git a/server/src/main.rs b/server/src/main.rs index aaa5798..994c291 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,10 +1,46 @@ -use std::env; +use std::{env, sync::Arc}; -use axum::{routing::get, Json, Router}; -use data::MyMessage; -use tracing::info; +use axum::{extract::{FromRequest, Extension}, routing::get, Json, Router, http::{Request, request::Parts}, body::Body}; +use openidconnect::{ + core::{CoreClient, CoreProviderMetadata, CoreResponseType}, + reqwest::async_http_client, + AccessTokenHash, AuthenticationFlow, AuthorizationCode, ClientId, ClientSecret, CsrfToken, + IssuerUrl, Nonce, OAuth2TokenResponse, PkceCodeChallenge, RedirectUrl, Scope, TokenResponse, url::Url, +}; +use protocol::UserInfo; +use tower_http::trace::TraceLayer; +use tower_cookies::{Cookie, CookieManagerLayer, Cookies}; +use tracing::{info, trace}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; -use tower_http::{trace::TraceLayer}; +mod auth; +use crate::auth::Authenticator; + +struct ServerContext { + pub app_url: String, + pub authenticator: Authenticator, +} +type ContextExtension = Extension<Arc<ServerContext>>; + +async fn keycloak_client( + issuer_url: IssuerUrl, + client_id: ClientId, + client_secret: ClientSecret, + redirect_uri: RedirectUrl, +) -> CoreClient { + // // Use OpenID Connect Discovery to fetch the provider metadata. + let provider_metadata = CoreProviderMetadata::discover_async(issuer_url, async_http_client) + .await + .unwrap(); + + let client = + CoreClient::from_provider_metadata(provider_metadata, client_id, Some(client_secret)) + // Set the URL the user will be redirected to after the authorization process. + .set_redirect_uri( + redirect_uri + ); + + client +} #[tokio::main] async fn main() { @@ -16,12 +52,23 @@ async fn main() { )) .with(tracing_subscriber::fmt::layer()) .init(); - + let bind_address = env::var("BIND_ADDRESS").unwrap(); info!("Starting server on {}", bind_address); + let app_url = env::var("APP_URL").unwrap(); + + let state = Arc::new(ServerContext { + app_url: app_url, + authenticator: Authenticator::from_env().await, + }); + let app = Router::new() - .route("/api/test", get(test)) + .route("/api/user/info", get(user_info)) + .route("/api/get_login_url", get(get_login_url)) + .route(auth::LOGIN_CALLBACK, get(login_callback)) + .layer(CookieManagerLayer::new()) + .layer(Extension(state)) .layer(TraceLayer::new_for_http()); axum::Server::bind(&bind_address.parse().unwrap()) @@ -30,8 +77,18 @@ async fn main() { .unwrap(); } -async fn test() -> Json<MyMessage> { - Json(MyMessage { - message: "Hello, ,World!".to_string(), - }) +async fn user_info() -> Json<Option<UserInfo>> { + Json(None) +} + +async fn login_callback(mut req: Parts) -> &'static str { + info!("{req:?}"); + "hello" +} + +async fn get_login_url(extension: ContextExtension) -> Json<Url> { + let (user_id, auth_url) = extension.authenticator.get_login_url().await; + trace!("Creating auth url for {user_id:?}"); + // cookies.add(Cookie::new("user-id", serde_json::to_string(user_id))); + Json(auth_url) } diff --git a/webapp/Cargo.toml b/webapp/Cargo.toml index fe7addb..5411ccd 100644 --- a/webapp/Cargo.toml +++ b/webapp/Cargo.toml @@ -18,7 +18,7 @@ regex = "1.0" lazy_static = "1.4" gloo-net = "0.2.4" wasm-bindgen-futures = "0.4.33" -data = { path = "../data" } +protocol = { path = "../protocol" } yew-router = "0.16.0" [dev-dependencies] diff --git a/webapp/src/components.rs b/webapp/src/components.rs index 80b5a91..224177b 100644 --- a/webapp/src/components.rs +++ b/webapp/src/components.rs @@ -1,5 +1,6 @@ use crate::card::Suit; +mod app_context_provider; mod bidding; mod bidding_box; mod bidding_table; @@ -10,6 +11,7 @@ mod show_bid; mod trick_in_play; mod tricks_played; +pub use self::app_context_provider::*; pub use self::bidding::*; pub use self::bidding_box::*; pub use self::bidding_table::*; diff --git a/webapp/src/components/app_context_provider.rs b/webapp/src/components/app_context_provider.rs new file mode 100644 index 0000000..f2938ff --- /dev/null +++ b/webapp/src/components/app_context_provider.rs @@ -0,0 +1,50 @@ +use gloo_net::http::Request; +use protocol::UserInfo; +use std::rc::Rc; +use yew::prelude::*; + +#[derive(Clone, Debug, PartialEq)] +pub struct AppContext { + pub user: Option<UserInfo>, +} + +#[derive(Properties, Clone, PartialEq)] +pub struct Props { + pub children: Children, +} + +#[function_component(AppContextProvider)] +pub fn app_context_provider(props: &Props) -> Html { + let context: UseStateHandle<Option<Rc<AppContext>>> = use_state(|| None); + + { + let context = context.clone(); + use_effect_with_deps( + move |_| { + wasm_bindgen_futures::spawn_local(async move { + let user_info: Option<UserInfo> = Request::get("/api/user/info") + .send() + .await + .unwrap() + .json() + .await + .unwrap(); + context.set(Some(Rc::new(AppContext { user: user_info }))); + }); + || () + }, + (), + ); + } + + match &*context { + None => html! { + <p>{ "Loading app..." }</p> + }, + Some(context) => html! { + <ContextProvider<Rc<AppContext>> {context}> + { for props.children.iter() } + </ContextProvider<Rc<AppContext>>> + }, + } +} diff --git a/webapp/src/main.rs b/webapp/src/main.rs index 6fcf59f..a3fcebc 100644 --- a/webapp/src/main.rs +++ b/webapp/src/main.rs @@ -1,4 +1,5 @@ -use data::MyMessage; +use std::rc::Rc; + #[allow(unused_imports)] use log::{debug, error, info, warn}; use yew::prelude::*; @@ -6,7 +7,7 @@ use yew_router::prelude::*; pub mod bridge_engine; pub mod card; pub mod components; -use components::Game; +use components::{AppContextProvider, AppContext, Game}; use gloo_net::http::Request; extern crate wee_alloc; @@ -30,48 +31,41 @@ fn main() { #[function_component(App)] pub fn app() -> Html { - let msg = use_state(|| "".to_string()); - { - let msg = msg.clone(); - use_effect_with_deps( - move |_| { - wasm_bindgen_futures::spawn_local(async move { - let m: MyMessage = Request::get("/api/test") - .send() - .await - .unwrap() - .json() - .await - .unwrap(); - msg.set(m.message) - }); - || () - }, - (), - ) + html! { + <> + <AppContextProvider> + <BrowserRouter> + <Switch<Route> render={Switch::render(switch)} /> + </BrowserRouter> + </AppContextProvider> + </> } +} + +#[function_component(Home)] +fn home() -> Html { + let ctx = use_context::<Rc<AppContext>>().unwrap(); - info!("Got message from server: {}", &*msg); + let user = match &ctx.user { + Some(userinfo) => html! { + <p>{ format!("Logged in as {}", userinfo.username) }</p> + }, + None => html! { <p>{ "Not logged in" }</p> }, + }; html! { <> - <BrowserRouter> - <Switch<Route> render={Switch::render(switch)} /> - </BrowserRouter> + { user } + <p> + <Link<Route> to={Route::Playground}>{ "Playground" }</Link<Route>> + </p> </> } } fn switch(routes: &Route) -> Html { match routes { - Route::Home => html! { - <> - <p>{ "Hello!" }</p> - <p> - <Link<Route> to={Route::Playground}>{ "Playground" }</Link<Route>> - </p> - </> - }, + Route::Home => html!{ <Home/> }, Route::Playground => html! { <div class="game-layout"><Game /></div> }, |