diff --git a/Cargo.lock b/Cargo.lock index 18d618f..4c8f0d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -184,16 +184,29 @@ dependencies = [ ] [[package]] -name = "async-executor" -version = "1.6.0" +name = "async-channel" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b0c4a4f319e45986f347ee47fef8bf5e81c9abc3f6f58dc2391439f30df65f0" +checksum = "d37875bd9915b7d67c2f117ea2c30a0989874d0b2cb694fe25403c85763c0c9e" dependencies = [ - "async-lock 2.8.0", + "concurrent-queue", + "event-listener 3.1.0", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc5ea910c42e5ab19012bab31f53cb4d63d54c3a27730f9a833a88efcf4bb52d" +dependencies = [ + "async-lock 3.1.1", "async-task", "concurrent-queue", "fastrand 2.0.1", - "futures-lite 1.13.0", + "futures-lite 2.0.1", "slab", ] @@ -203,7 +216,7 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" dependencies = [ - "async-channel", + "async-channel 1.9.0", "async-executor", "async-io 1.13.0", "async-lock 2.8.0", @@ -238,14 +251,14 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41ed9d5715c2d329bf1b4da8d60455b99b187f27ba726df2883799af9af60997" dependencies = [ - "async-lock 3.0.0", + "async-lock 3.1.1", "cfg-if 1.0.0", "concurrent-queue", "futures-io", "futures-lite 2.0.1", "parking", "polling 3.3.0", - "rustix 0.38.21", + "rustix 0.38.25", "slab", "tracing", "waker-fn", @@ -263,11 +276,11 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.0.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e900cdcd39bb94a14487d3f7ef92ca222162e6c7c3fe7cb3550ea75fb486ed" +checksum = "655b9c7fe787d3b25cc0f804a1a8401790f0c5bc395beb5a64dc77d8de079105" dependencies = [ - "event-listener 3.0.1", + "event-listener 3.1.0", "event-listener-strategy", "pin-project-lite", ] @@ -295,9 +308,9 @@ dependencies = [ "async-signal", "blocking", "cfg-if 1.0.0", - "event-listener 3.0.1", + "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.21", + "rustix 0.38.25", "windows-sys", ] @@ -334,7 +347,7 @@ dependencies = [ "cfg-if 1.0.0", "futures-core", "futures-io", - "rustix 0.38.21", + "rustix 0.38.25", "signal-hook-registry", "slab", "windows-sys", @@ -356,7 +369,7 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" dependencies = [ - "async-channel", + "async-channel 1.9.0", "async-global-executor", "async-io 1.13.0", "async-lock 2.8.0", @@ -427,7 +440,7 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" version = "0.6.16" -source = "git+https://github.com/tokio-rs/axum?branch=main#3ff45d9c96b5192af6b6ec26eb2a2bfcddd00d7d" +source = "git+https://github.com/tokio-rs/axum?branch=main#30afe97e99303fffc4bf2f411a93022b5bc1ba35" dependencies = [ "async-trait", "axum-core 0.3.4 (git+https://github.com/tokio-rs/axum?branch=main)", @@ -512,7 +525,7 @@ dependencies = [ [[package]] name = "axum-core" version = "0.3.4" -source = "git+https://github.com/tokio-rs/axum?branch=main#3ff45d9c96b5192af6b6ec26eb2a2bfcddd00d7d" +source = "git+https://github.com/tokio-rs/axum?branch=main#30afe97e99303fffc4bf2f411a93022b5bc1ba35" dependencies = [ "async-trait", "bytes", @@ -530,7 +543,7 @@ dependencies = [ [[package]] name = "axum-extra" version = "0.7.4" -source = "git+https://github.com/tokio-rs/axum?branch=main#3ff45d9c96b5192af6b6ec26eb2a2bfcddd00d7d" +source = "git+https://github.com/tokio-rs/axum?branch=main#30afe97e99303fffc4bf2f411a93022b5bc1ba35" dependencies = [ "axum 0.6.16", "axum-core 0.3.4 (git+https://github.com/tokio-rs/axum?branch=main)", @@ -594,7 +607,7 @@ dependencies = [ [[package]] name = "axum-macros" version = "0.3.7" -source = "git+https://github.com/tokio-rs/axum?branch=main#3ff45d9c96b5192af6b6ec26eb2a2bfcddd00d7d" +source = "git+https://github.com/tokio-rs/axum?branch=main#30afe97e99303fffc4bf2f411a93022b5bc1ba35" dependencies = [ "heck", "proc-macro2", @@ -684,7 +697,7 @@ version = "0.1.0" dependencies = [ "anyhow", "axum 0.6.16", - "clap 4.4.7", + "clap 4.4.8", "nefarious-login", "tokio", "tracing-subscriber", @@ -749,16 +762,16 @@ dependencies = [ [[package]] name = "blocking" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c36a4d0d48574b3dd360b4b7d95cc651d2b6557b6402848a27d4b228a473e2a" +checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ - "async-channel", - "async-lock 2.8.0", + "async-channel 2.1.0", + "async-lock 3.1.1", "async-task", "fastrand 2.0.1", "futures-io", - "futures-lite 1.13.0", + "futures-lite 2.0.1", "piper", "tracing", ] @@ -833,7 +846,7 @@ version = "0.1.0" dependencies = [ "anyhow", "axum 0.6.16", - "clap 4.4.7", + "clap 4.4.8", "nefarious-login", "tokio", "tracing-subscriber", @@ -841,9 +854,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.7" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ "clap_builder", "clap_derive", @@ -851,9 +864,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.7" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" dependencies = [ "anstream", "anstyle", @@ -999,9 +1012,9 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", "rand_core", @@ -1083,6 +1096,18 @@ version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f8a51dd197fa6ba5b4dc98a990a43cc13693c23eb0089ebb0fcc1f04152bca6" +[[package]] +name = "custom_redirect" +version = "0.1.0" +dependencies = [ + "anyhow", + "axum 0.6.16", + "clap 4.4.8", + "nefarious-login", + "tokio", + "tracing-subscriber", +] + [[package]] name = "darling" version = "0.20.3" @@ -1206,9 +1231,9 @@ checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" [[package]] name = "ecdsa" -version = "0.16.8" +version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", "digest 0.10.7", @@ -1230,14 +1255,15 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" +checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" dependencies = [ "curve25519-dalek", "ed25519", "serde", "sha2 0.10.8", + "subtle", "zeroize", ] @@ -1252,9 +1278,9 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.13.6" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97ca172ae9dc9f9b779a6e3a65d308f2af74e5b8c921299075bdb4a0370e914" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", @@ -1288,9 +1314,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e" +checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" dependencies = [ "libc", "windows-sys", @@ -1315,9 +1341,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "3.0.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cec0252c2afff729ee6f00e903d479fba81784c8e2bd77447673471fdfaea1" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" dependencies = [ "concurrent-queue", "parking", @@ -1330,7 +1356,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" dependencies = [ - "event-listener 3.0.1", + "event-listener 3.1.0", "pin-project-lite", ] @@ -1361,9 +1387,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f69037fe1b785e84986b4f2cbcf647381876a00671d25ceef715d7812dd7e1dd" +checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" [[package]] name = "finl_unicode" @@ -1509,7 +1535,11 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3831c2651acb5177cbd83943f3d9c8912c5ad03c76afcc0e9511ba568ec5ebb" dependencies = [ + "fastrand 2.0.1", "futures-core", + "futures-io", + "memchr", + "parking", "pin-project-lite", ] @@ -1619,9 +1649,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.21" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" dependencies = [ "bytes", "fnv", @@ -1629,7 +1659,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap 2.1.0", "slab", "tokio", "tokio-util", @@ -1763,9 +1793,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f95b9abcae896730d42b78e09c155ed4ddf82c07b4de772c64aee5b2d8b7c150" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -2207,7 +2237,7 @@ dependencies = [ "axum 0.6.16", "axum-extra 0.7.4", "axum-sessions", - "clap 4.4.7", + "clap 4.4.8", "oauth2", "openidconnect", "pretty_assertions", @@ -2239,7 +2269,7 @@ version = "0.1.0" dependencies = [ "anyhow", "axum 0.6.16", - "clap 4.4.7", + "clap 4.4.8", "nefarious-login", "tokio", "tracing-subscriber", @@ -2666,7 +2696,7 @@ dependencies = [ "cfg-if 1.0.0", "concurrent-queue", "pin-project-lite", - "rustix 0.38.21", + "rustix 0.38.25", "tracing", "windows-sys", ] @@ -2707,9 +2737,9 @@ dependencies = [ [[package]] name = "primeorder" -version = "0.13.3" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7dbe9ed3b56368bd99483eb32fe9c17fdd3730aebadc906918ce78d54c7eeb4" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" dependencies = [ "elliptic-curve", ] @@ -2907,9 +2937,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ef35bf3e7fe15a53c4ab08a998e42271eab13eb0db224126bc7bc4c4bad96d" +checksum = "6a3211b01eea83d80687da9eef70e39d65144a3894866a5153a2723e425a157f" dependencies = [ "const-oid", "digest 0.10.7", @@ -2956,9 +2986,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ "bitflags 2.4.1", "errno", @@ -2969,9 +2999,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.8" +version = "0.21.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446e14c5cda4f3f30fe71863c34ec70f5ac79d6087097ad0bb433e1be5edf04c" +checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" dependencies = [ "log", "ring", @@ -3114,9 +3144,9 @@ checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" [[package]] name = "serde" -version = "1.0.192" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] @@ -3133,9 +3163,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", @@ -3279,9 +3309,9 @@ dependencies = [ [[package]] name = "signature" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest 0.10.7", "rand_core", @@ -3747,7 +3777,7 @@ dependencies = [ "cfg-if 1.0.0", "fastrand 2.0.1", "redox_syscall 0.4.1", - "rustix 0.38.21", + "rustix 0.38.25", "windows-sys", ] @@ -3987,9 +4017,9 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.4" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ "log", "once_cell", @@ -3998,9 +4028,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", @@ -4095,9 +4125,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.5.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" dependencies = [ "getrandom", ] @@ -4363,18 +4393,18 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" [[package]] name = "zerocopy" -version = "0.7.25" +version = "0.7.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557" +checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.25" +version = "0.7.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b" +checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" dependencies = [ "proc-macro2", "quote", @@ -4383,9 +4413,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" [[package]] name = "zitadel" diff --git a/crates/nefarious-login/src/auth.rs b/crates/nefarious-login/src/auth.rs index 80cd561..81b7b0f 100644 --- a/crates/nefarious-login/src/auth.rs +++ b/crates/nefarious-login/src/auth.rs @@ -14,9 +14,14 @@ use crate::{ #[async_trait] pub trait Auth { - async fn login(&self) -> anyhow::Result; + async fn login(&self, return_url: Option) -> anyhow::Result; async fn login_token(&self, user: &str, password: &str) -> anyhow::Result; - async fn login_authorized(&self, code: &str, state: &str) -> anyhow::Result<(HeaderMap, Url)>; + async fn login_authorized( + &self, + code: &str, + state: &str, + return_url: Option, + ) -> anyhow::Result<(HeaderMap, Url)>; async fn get_user_from_session(&self, cookie: &str) -> anyhow::Result; } @@ -87,12 +92,17 @@ pub static COOKIE_NAME: &str = "SESSION"; #[async_trait] impl Auth for ZitadelAuthService { - async fn login(&self) -> anyhow::Result { - let authorize_url = self.oauth.authorize_url().await?; + async fn login(&self, return_url: Option) -> anyhow::Result { + let authorize_url = self.oauth.authorize_url(return_url).await?; Ok(authorize_url) } - async fn login_authorized(&self, code: &str, _state: &str) -> anyhow::Result<(HeaderMap, Url)> { + async fn login_authorized( + &self, + code: &str, + _state: &str, + return_path: Option, + ) -> anyhow::Result<(HeaderMap, Url)> { let token = self.oauth.exchange(code).await?; let id_token = self.introspection.get_id_token(token.as_str()).await?; let cookie_value = self.session.insert_user("user", id_token).await?; @@ -102,9 +112,14 @@ impl Auth for ZitadelAuthService { let mut headers = HeaderMap::new(); headers.insert(SET_COOKIE, cookie.parse().unwrap()); + let mut return_url = self.config.return_url.clone(); + if let Some(return_path) = return_path { + return_url.push_str(&format!("?returnPath={return_path}")); + } + Ok(( headers, - Url::parse(&self.config.return_url) + Url::parse(&return_url) .context("failed to parse login_authorized zitadel return url")?, )) } @@ -126,7 +141,7 @@ pub struct NoopAuthService { #[async_trait] impl Auth for NoopAuthService { - async fn login(&self) -> anyhow::Result { + async fn login(&self, return_url: Option) -> anyhow::Result { let url = Url::parse(&format!( "{}/auth/authorized?code=noop&state=noop", self.config @@ -142,6 +157,7 @@ impl Auth for NoopAuthService { &self, _code: &str, _state: &str, + _return_url: Option, ) -> anyhow::Result<(HeaderMap, Url)> { let cookie_value = self .session diff --git a/crates/nefarious-login/src/axum.rs b/crates/nefarious-login/src/axum.rs index 73d0663..acb74d6 100644 --- a/crates/nefarious-login/src/axum.rs +++ b/crates/nefarious-login/src/axum.rs @@ -18,7 +18,6 @@ use crate::session::User; #[derive(Debug, Deserialize)] pub struct ZitadelAuthParams { - #[allow(dead_code)] return_url: Option, } @@ -51,7 +50,7 @@ where pub async fn zitadel_auth( State(auth_service): State, ) -> Result { - let url = auth_service.login().await.into_response()?; + let url = auth_service.login(None).await.into_response()?; Ok(Redirect::to(url.as_ref())) } @@ -61,6 +60,8 @@ pub async fn zitadel_auth( pub struct AuthRequest { code: String, state: String, + #[serde(alias = "returnUrl")] + return_url: Option, } pub async fn login_authorized( @@ -68,7 +69,7 @@ pub async fn login_authorized( State(auth_service): State, ) -> Result { let (headers, url) = auth_service - .login_authorized(&query.code, &query.state) + .login_authorized(&query.code, &query.state, query.return_url) .await .into_response()?; diff --git a/crates/nefarious-login/src/oauth.rs b/crates/nefarious-login/src/oauth.rs index bc0da8c..27059d8 100644 --- a/crates/nefarious-login/src/oauth.rs +++ b/crates/nefarious-login/src/oauth.rs @@ -31,7 +31,7 @@ impl Deref for OAuth { #[async_trait] pub trait OAuthClient { async fn get_token(&self) -> anyhow::Result<()>; - async fn authorize_url(&self) -> anyhow::Result; + async fn authorize_url(&self, return_url: Option) -> anyhow::Result; async fn exchange(&self, code: &str) -> anyhow::Result; } diff --git a/crates/nefarious-login/src/oauth/noop.rs b/crates/nefarious-login/src/oauth/noop.rs index 5d5432a..020779d 100644 --- a/crates/nefarious-login/src/oauth/noop.rs +++ b/crates/nefarious-login/src/oauth/noop.rs @@ -10,7 +10,7 @@ impl OAuthClient for NoopOAuthClient { async fn get_token(&self) -> anyhow::Result<()> { Ok(()) } - async fn authorize_url(&self) -> anyhow::Result { + async fn authorize_url(&self, return_url: Option) -> anyhow::Result { Ok(Url::parse("http://localhost:3000/auth/zitadel").unwrap()) } diff --git a/crates/nefarious-login/src/oauth/zitadel.rs b/crates/nefarious-login/src/oauth/zitadel.rs index d889494..a144157 100644 --- a/crates/nefarious-login/src/oauth/zitadel.rs +++ b/crates/nefarious-login/src/oauth/zitadel.rs @@ -104,15 +104,28 @@ impl OAuthClient for ZitadelOAuthClient { async fn get_token(&self) -> anyhow::Result<()> { Ok(()) } - async fn authorize_url(&self) -> anyhow::Result { - let (auth_url, _csrf_token) = self + async fn authorize_url(&self, return_url: Option) -> anyhow::Result { + let req = self .client .authorize_url(CsrfToken::new_random) .add_scope(Scope::new("identify".to_string())) .add_scope(Scope::new("openid".to_string())) .add_scope(Scope::new("email".to_string())) - .add_scope(Scope::new("profile".to_string())) - .url(); + .add_scope(Scope::new("profile".to_string())); + + let req = { + if let Some(return_url) = return_url { + let mut redirect_url = self.client.redirect_url().unwrap().as_str().to_string(); + + redirect_url.push_str(&format!("?returnUrl={}", return_url)); + + req.set_redirect_uri(std::borrow::Cow::Owned(RedirectUrl::new(redirect_url)?)) + } else { + req + } + }; + + let (auth_url, _csrf_token) = req.url(); Ok(auth_url) } diff --git a/cuddle.yaml b/cuddle.yaml index 246a8fd..7dfc989 100644 --- a/cuddle.yaml +++ b/cuddle.yaml @@ -5,3 +5,9 @@ base: "git@git.front.kjuulh.io:kjuulh/cuddle-base.git" vars: service: "nefarious-login" registry: kasperhermansen + +scripts: + local_up: + type: shell + local_down: + type: shell diff --git a/examples/custom_redirect/Cargo.toml b/examples/custom_redirect/Cargo.toml new file mode 100644 index 0000000..299c651 --- /dev/null +++ b/examples/custom_redirect/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "custom_redirect" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +nefarious-login.workspace = true + +tokio.workspace = true +anyhow.workspace = true +axum.workspace = true +clap.workspace = true + +tracing-subscriber.workspace = true diff --git a/examples/custom_redirect/src/main.rs b/examples/custom_redirect/src/main.rs new file mode 100644 index 0000000..a5a13bb --- /dev/null +++ b/examples/custom_redirect/src/main.rs @@ -0,0 +1,94 @@ +use std::{net::SocketAddr, str::FromStr}; + +use axum::{ + extract::{FromRef, State}, + response::{IntoResponse, Redirect}, + routing::get, + Router, +}; +use nefarious_login::{ + auth::AuthService, + axum::{AuthController, UserFromSession}, + login::{ + auth_clap::{AuthEngine, ZitadelClap}, + config::ConfigClap, + AuthClap, + }, + session::{PostgresqlSessionClap, SessionBackend}, +}; +use tracing_subscriber::EnvFilter; + +#[derive(Clone)] +struct AppState { + auth: AuthService, +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .init(); + + let auth = AuthClap { + engine: AuthEngine::Zitadel, + session_backend: SessionBackend::Postgresql, + zitadel: ZitadelClap { + authority_url: Some("https://personal-wxuujs.zitadel.cloud".into()), + client_id: Some("237412977047895154@nefarious-test".into()), + client_secret: Some( + "rWwDi8gjNOyuMFKoOjNSlhjcVZ1B25wDh6HsDL27f0g2Hb0xGbvEf0WXFY2akOlL".into(), + ), + redirect_url: Some("http://localhost:3001/auth/authorized".into()), + }, + session: nefarious_login::session::SessionClap { + postgresql: PostgresqlSessionClap { + conn: Some("postgres://nefarious-test:somenotverysecurepassword@localhost:5432/nefarious-test".into()), + }, + }, + config: ConfigClap { return_url: "http://localhost:3001".into() } // this normally has /authed + }; + + let auth_service = AuthService::new(&auth).await?; + + let state = AppState { + auth: auth_service.clone(), + }; + + let app = Router::new() + .route("/unauthed", get(unauthed)) + .route("/authed", get(authed)) + .route("/login", get(login)) + .with_state(state) + .nest("/auth", AuthController::new_router(auth_service).await?); + + let addr = SocketAddr::from_str(&format!("{}:{}", "127.0.0.1", "3000"))?; + let listener = tokio::net::TcpListener::bind(&addr).await?; + + axum::serve(listener, app).await?; + + Ok(()) +} + +impl FromRef for AuthService { + fn from_ref(input: &AppState) -> Self { + input.auth.clone() + } +} + +async fn login(State(auth_service): State) -> impl IntoResponse { + let url = auth_service.login(Some("/authed".into())).await.unwrap(); + + Redirect::to(url.as_ref()) +} + +async fn unauthed() -> String { + "Hello Unauthorized User".into() +} + +#[axum::debug_handler()] +async fn authed( + user: UserFromSession, + State(_auth_service): State, +) -> impl IntoResponse { + format!("Hello authorized user: {:?}", user.user.id) +} diff --git a/scripts/local_down.sh b/scripts/local_down.sh new file mode 100755 index 0000000..cbb90a3 --- /dev/null +++ b/scripts/local_down.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +cuddle render_template --template-file $TMP/docker-compose.local_up.yml.tmpl --dest $TMP/docker-compose.local_up.yml + +docker compose -f $TMP/docker-compose.local_up.yml down -v diff --git a/scripts/local_up.sh b/scripts/local_up.sh new file mode 100755 index 0000000..d215338 --- /dev/null +++ b/scripts/local_up.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -e + +cuddle render_template --template-file $TMP/docker-compose.local_up.yml.tmpl --dest $TMP/docker-compose.local_up.yml + +docker compose -f $TMP/docker-compose.local_up.yml up -d --remove-orphans --build + +sleep 3 diff --git a/templates/docker-compose.local_up.dockerignore b/templates/docker-compose.local_up.dockerignore new file mode 100644 index 0000000..53f730a --- /dev/null +++ b/templates/docker-compose.local_up.dockerignore @@ -0,0 +1,7 @@ +target/ +.git/ +.cuddle/ +scripts/ +cuddle.yaml +local.sh +README.md diff --git a/templates/docker-compose.local_up.yml.tmpl b/templates/docker-compose.local_up.yml.tmpl new file mode 100644 index 0000000..5760c45 --- /dev/null +++ b/templates/docker-compose.local_up.yml.tmpl @@ -0,0 +1,17 @@ +version: '3.7' + +services: + db: + image: bitnami/postgresql:16 + restart: always + environment: + - POSTGRESQL_USERNAME=nefarious-test + - POSTGRESQL_DATABASE=nefarious-test + - POSTGRESQL_PASSWORD=somenotverysecurepassword + ports: + - 5432:5432 + volumes: + - pgdata:/var/lib/postgresql/data + +volumes: + pgdata: