diff --git a/Cargo.lock b/Cargo.lock index 3eebad384d..66fe4f12eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,7 +33,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cipher", "cpufeatures", ] @@ -58,7 +58,7 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "getrandom 0.2.15", "once_cell", "version_check", @@ -122,18 +122,6 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "askama" version = "0.12.1" @@ -206,32 +194,13 @@ dependencies = [ [[package]] name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener 2.5.3", -] - -[[package]] -name = "async-session" -version = "3.0.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07da4ce523b4e2ebaaf330746761df23a465b951a83d84bbce4233dabedae630" +checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" dependencies = [ - "anyhow", - "async-lock", - "async-trait", - "base64 0.13.1", - "bincode", - "blake3", - "chrono", - "hmac 0.11.0", - "log", - "rand 0.8.5", - "serde", - "serde_json", - "sha2 0.9.9", + "event-listener", + "event-listener-strategy", + "pin-project-lite", ] [[package]] @@ -305,7 +274,7 @@ name = "axum" version = "0.8.4" dependencies = [ "anyhow", - "axum-core", + "axum-core 0.5.2", "axum-extra", "axum-macros", "base64 0.22.1", @@ -372,12 +341,31 @@ dependencies = [ "tracing", ] +[[package]] +name = "axum-core" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" +dependencies = [ + "bytes", + "futures-core", + "http 1.2.0", + "http-body 1.0.1", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 1.0.2", + "tower-layer", + "tower-service", +] + [[package]] name = "axum-extra" version = "0.10.1" dependencies = [ "axum", - "axum-core", + "axum-core 0.5.2", "axum-macros", "bytes", "cookie", @@ -483,7 +471,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object", @@ -569,15 +557,6 @@ dependencies = [ "redis", ] -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - [[package]] name = "bindgen" version = "0.69.5" @@ -628,30 +607,6 @@ dependencies = [ "wyz", ] -[[package]] -name = "blake3" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if 0.1.10", - "constant_time_eq", - "crypto-mac 0.8.0", - "digest 0.9.0", -] - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -752,12 +707,6 @@ dependencies = [ "nom", ] -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -844,12 +793,6 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - [[package]] name = "convert_case" version = "0.4.0" @@ -865,10 +808,10 @@ dependencies = [ "aes-gcm", "base64 0.22.1", "hkdf", - "hmac 0.12.1", + "hmac", "percent-encoding", "rand 0.8.5", - "sha2 0.10.8", + "sha2", "subtle", "time", "version_check", @@ -920,7 +863,16 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", ] [[package]] @@ -958,26 +910,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "crypto-mac" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "crypto-mac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" -dependencies = [ - "generic-array", - "subtle", -] - [[package]] name = "ctr" version = "0.9.2" @@ -1174,22 +1106,13 @@ dependencies = [ "syn 2.0.93", ] -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", + "block-buffer", "const-oid", "crypto-common", "subtle", @@ -1247,7 +1170,7 @@ version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1294,17 +1217,11 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "home", "windows-sys 0.48.0", ] -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - [[package]] name = "event-listener" version = "5.3.1" @@ -1316,6 +1233,16 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + [[package]] name = "eventsource-stream" version = "0.2.3" @@ -1628,16 +1555,23 @@ name = "example-oauth" version = "0.1.0" dependencies = [ "anyhow", - "async-session", "axum", "axum-extra", "http 1.2.0", "oauth2", "reqwest 0.12.12", + "rusqlite", "serde", + "serde_json", + "tempfile", + "time", "tokio", + "tower-sessions", + "tower-sessions-moka-store", + "tower-sessions-rusqlite-store", "tracing", "tracing-subscriber", + "uuid", ] [[package]] @@ -2010,6 +1944,18 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + [[package]] name = "fastrand" version = "2.3.0" @@ -2079,6 +2025,20 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.31" @@ -2169,6 +2129,20 @@ dependencies = [ "slab", ] +[[package]] +name = "generator" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" +dependencies = [ + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -2185,7 +2159,7 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", @@ -2198,7 +2172,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", @@ -2354,7 +2328,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92652067c9ce6f66ce53cc38d1169daa36e6e7eb7dd3b63b5103bd9d97117248" dependencies = [ "async-trait", - "cfg-if 1.0.0", + "cfg-if", "data-encoding", "enum-as-inner", "futures-channel", @@ -2377,7 +2351,7 @@ version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a2e2aba9c389ce5267d31cf1e4dace82390ae276b0b364ea55630b1fa1b44b4" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "futures-util", "hickory-proto", "ipconfig", @@ -2398,17 +2372,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ - "hmac 0.12.1", -] - -[[package]] -name = "hmac" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" -dependencies = [ - "crypto-mac 0.11.0", - "digest 0.9.0", + "hmac", ] [[package]] @@ -2417,7 +2381,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] @@ -2646,7 +2610,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -2897,9 +2861,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", @@ -2947,7 +2911,7 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "windows-targets 0.52.6", ] @@ -2980,6 +2944,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + [[package]] name = "listenfd" version = "1.0.1" @@ -3005,6 +2975,7 @@ checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", + "serde", ] [[package]] @@ -3013,6 +2984,19 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + [[package]] name = "lru-cache" version = "0.1.2" @@ -3049,8 +3033,8 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ - "cfg-if 1.0.0", - "digest 0.10.7", + "cfg-if", + "digest", ] [[package]] @@ -3170,6 +3154,28 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "moka" +version = "0.12.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926" +dependencies = [ + "async-lock", + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "event-listener", + "futures-util", + "loom", + "parking_lot", + "portable-atomic", + "rustc_version", + "smallvec", + "tagptr", + "thiserror 1.0.69", + "uuid", +] + [[package]] name = "mongodb" version = "3.1.1" @@ -3190,7 +3196,7 @@ dependencies = [ "hex", "hickory-proto", "hickory-resolver", - "hmac 0.12.1", + "hmac", "md-5", "mongodb-internal-macros", "once_cell", @@ -3204,7 +3210,7 @@ dependencies = [ "serde_bytes", "serde_with", "sha-1", - "sha2 0.10.8", + "sha2", "socket2", "stringprep", "strsim", @@ -3371,7 +3377,7 @@ dependencies = [ "serde", "serde_json", "serde_path_to_error", - "sha2 0.10.8", + "sha2", "thiserror 1.0.69", "url", ] @@ -3404,7 +3410,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" dependencies = [ "bitflags 2.6.0", - "cfg-if 1.0.0", + "cfg-if", "foreign-types", "libc", "once_cell", @@ -3469,7 +3475,7 @@ version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall", "smallvec", @@ -3488,7 +3494,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] @@ -3599,7 +3605,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "opaque-debug", "universal-hash", @@ -3620,12 +3626,12 @@ dependencies = [ "base64 0.22.1", "byteorder", "bytes", - "fallible-iterator", - "hmac 0.12.1", + "fallible-iterator 0.2.0", + "hmac", "md-5", "memchr", "rand 0.8.5", - "sha2 0.10.8", + "sha2", "stringprep", ] @@ -3636,7 +3642,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f66ea23a2d0e5734297357705193335e0a957696f34bed2f2faefacb2fec336f" dependencies = [ "bytes", - "fallible-iterator", + "fallible-iterator 0.2.0", "postgres-protocol", ] @@ -3784,7 +3790,7 @@ dependencies = [ "rustc-hash 2.1.0", "rustls 0.23.20", "socket2", - "thiserror 2.0.9", + "thiserror 2.0.12", "tokio", "tracing", ] @@ -3803,7 +3809,7 @@ dependencies = [ "rustls 0.23.20", "rustls-pki-types", "slab", - "thiserror 2.0.9", + "thiserror 2.0.12", "tinyvec", "tracing", "web-time", @@ -4115,13 +4121,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", - "cfg-if 1.0.0", + "cfg-if", "getrandom 0.2.15", "libc", "untrusted", "windows-sys 0.52.0", ] +[[package]] +name = "rmp" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" +dependencies = [ + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + [[package]] name = "rsa" version = "0.9.7" @@ -4129,7 +4157,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" dependencies = [ "const-oid", - "digest 0.10.7", + "digest", "num-bigint-dig", "num-integer", "num-traits", @@ -4142,6 +4170,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rusqlite" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7753b721174eb8ff87a9a0e799e2d7bc3749323e773db92e0984debb00019d6e" +dependencies = [ + "bitflags 2.6.0", + "fallible-iterator 0.3.0", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -4188,7 +4230,20 @@ dependencies = [ "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.14", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys 0.9.4", "windows-sys 0.59.0", ] @@ -4299,6 +4354,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -4466,9 +4527,9 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -4477,9 +4538,9 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -4488,28 +4549,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "sha2" version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -4542,7 +4590,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest 0.10.7", + "digest", "rand_core 0.6.4", ] @@ -4652,7 +4700,7 @@ dependencies = [ "crc", "crossbeam-queue", "either", - "event-listener 5.3.1", + "event-listener", "futures-channel", "futures-core", "futures-intrusive", @@ -4671,7 +4719,7 @@ dependencies = [ "rustls-pemfile 2.2.0", "serde", "serde_json", - "sha2 0.10.8", + "sha2", "smallvec", "sqlformat", "thiserror 1.0.69", @@ -4710,7 +4758,7 @@ dependencies = [ "quote", "serde", "serde_json", - "sha2 0.10.8", + "sha2", "sqlx-core", "sqlx-mysql", "sqlx-postgres", @@ -4733,7 +4781,7 @@ dependencies = [ "byteorder", "bytes", "crc", - "digest 0.10.7", + "digest", "dotenvy", "either", "futures-channel", @@ -4743,7 +4791,7 @@ dependencies = [ "generic-array", "hex", "hkdf", - "hmac 0.12.1", + "hmac", "itoa", "log", "md-5", @@ -4754,7 +4802,7 @@ dependencies = [ "rsa", "serde", "sha1", - "sha2 0.10.8", + "sha2", "smallvec", "sqlx-core", "stringprep", @@ -4782,7 +4830,7 @@ dependencies = [ "futures-util", "hex", "hkdf", - "hmac 0.12.1", + "hmac", "home", "itoa", "log", @@ -4792,7 +4840,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "sha2 0.10.8", + "sha2", "smallvec", "sqlx-core", "stringprep", @@ -4943,6 +4991,12 @@ dependencies = [ "libc", ] +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "take_mut" version = "0.2.2" @@ -4963,14 +5017,14 @@ checksum = "42a4d50cdb458045afc8131fd91b64904da29548bcb63c7236e0844936c13078" [[package]] name = "tempfile" -version = "3.14.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ - "cfg-if 1.0.0", "fastrand", + "getrandom 0.3.3", "once_cell", - "rustix", + "rustix 1.0.8", "windows-sys 0.59.0", ] @@ -4994,11 +5048,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.9" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ - "thiserror-impl 2.0.9", + "thiserror-impl 2.0.12", ] [[package]] @@ -5014,9 +5068,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.9" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", @@ -5029,7 +5083,7 @@ version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", ] @@ -5148,7 +5202,7 @@ dependencies = [ "async-trait", "byteorder", "bytes", - "fallible-iterator", + "fallible-iterator 0.2.0", "futures-channel", "futures-util", "log", @@ -5165,6 +5219,17 @@ dependencies = [ "whoami", ] +[[package]] +name = "tokio-rusqlite" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b65501378eb676f400c57991f42cbd0986827ab5c5200c53f206d710fb32a945" +dependencies = [ + "crossbeam-channel", + "rusqlite", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.24.1" @@ -5291,6 +5356,22 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-cookies" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "151b5a3e3c45df17466454bb74e9ecedecc955269bdedbf4d150dfa393b55a36" +dependencies = [ + "axum-core 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie", + "futures-util", + "http 1.2.0", + "parking_lot", + "pin-project-lite", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-http" version = "0.5.2" @@ -5360,6 +5441,84 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" +[[package]] +name = "tower-sessions" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a05911f23e8fae446005fe9b7b97e66d95b6db589dc1c4d59f6a2d4d4927d3" +dependencies = [ + "async-trait", + "http 1.2.0", + "time", + "tokio", + "tower-cookies", + "tower-layer", + "tower-service", + "tower-sessions-core", + "tower-sessions-memory-store", + "tracing", +] + +[[package]] +name = "tower-sessions-core" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8cce604865576b7751b7a6bc3058f754569a60d689328bb74c52b1d87e355b" +dependencies = [ + "async-trait", + "axum-core 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.22.1", + "futures", + "http 1.2.0", + "parking_lot", + "rand 0.8.5", + "serde", + "serde_json", + "thiserror 2.0.12", + "time", + "tokio", + "tracing", +] + +[[package]] +name = "tower-sessions-memory-store" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb05909f2e1420135a831dd5df9f5596d69196d0a64c3499ca474c4bd3d33242" +dependencies = [ + "async-trait", + "time", + "tokio", + "tower-sessions-core", +] + +[[package]] +name = "tower-sessions-moka-store" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5e622001aa59953f422ade78a0fa0d1f4d2566c9bf697bffe6aa89f1438f08" +dependencies = [ + "async-trait", + "moka", + "time", + "tower-sessions-core", +] + +[[package]] +name = "tower-sessions-rusqlite-store" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ac7b323ab3c35fbce2f2baad32f636986cdc7d8aba756468857bba1f121dbd" +dependencies = [ + "async-trait", + "rmp-serde", + "rusqlite", + "thiserror 2.0.12", + "time", + "tokio-rusqlite", + "tower-sessions-core", +] + [[package]] name = "tracing" version = "0.1.41" @@ -5469,7 +5628,7 @@ dependencies = [ "log", "rand 0.9.1", "sha1", - "thiserror 2.0.9", + "thiserror 2.0.12", "utf-8", ] @@ -5587,12 +5746,14 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.11.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.3.3", + "js-sys", "serde", + "wasm-bindgen", ] [[package]] @@ -5675,20 +5836,21 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", @@ -5700,11 +5862,11 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.49" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "once_cell", "wasm-bindgen", @@ -5713,9 +5875,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5723,9 +5885,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -5736,9 +5898,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "wasm-streams" @@ -5755,9 +5920,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -5797,7 +5962,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix", + "rustix 0.38.42", ] [[package]] @@ -5848,6 +6013,28 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -5857,14 +6044,76 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.93", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.93", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link", +] + [[package]] name = "windows-registry" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ - "windows-result", - "windows-strings", + "windows-result 0.2.0", + "windows-strings 0.1.0", "windows-targets 0.52.6", ] @@ -5877,16 +6126,34 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-strings" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ - "windows-result", + "windows-result 0.2.0", "windows-targets 0.52.6", ] +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -5945,6 +6212,15 @@ dependencies = [ "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -6050,7 +6326,7 @@ version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "windows-sys 0.48.0", ] diff --git a/examples/oauth/Cargo.toml b/examples/oauth/Cargo.toml index aafa29f4dc..da312f2dc3 100644 --- a/examples/oauth/Cargo.toml +++ b/examples/oauth/Cargo.toml @@ -6,14 +6,21 @@ publish = false [dependencies] anyhow = "1" -async-session = "3.0.0" axum = { path = "../../axum" } axum-extra = { path = "../../axum-extra", features = ["typed-header"] } http = "1.0.0" oauth2 = "4.1" # Use Rustls because it makes it easier to cross-compile on CI reqwest = { version = "0.12", default-features = false, features = ["rustls-tls", "json"] } +rusqlite = { version = "0.32.0", features = ["bundled"] } serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0.128" +tempfile = "3.19.1" +time = "0.3.36" tokio = { version = "1.0", features = ["full"] } +tower-sessions = "0.14.0" +tower-sessions-moka-store = "0.15.0" +tower-sessions-rusqlite-store = "0.14.0" tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } +uuid = { version = "1.15.1", features = ["v4","serde"] } diff --git a/examples/oauth/src/main.rs b/examples/oauth/src/main.rs index 8bea2c29b0..a5f977d5df 100644 --- a/examples/oauth/src/main.rs +++ b/examples/oauth/src/main.rs @@ -9,26 +9,44 @@ //! ``` use anyhow::{anyhow, Context, Result}; -use async_session::{MemoryStore, Session, SessionStore}; use axum::{ - extract::{FromRef, FromRequestParts, OptionalFromRequestParts, Query, State}, + extract::{Query, State}, http::{header::SET_COOKIE, HeaderMap}, response::{IntoResponse, Redirect, Response}, routing::get, - RequestPartsExt, Router, + Router, }; -use axum_extra::{headers, typed_header::TypedHeaderRejectionReason, TypedHeader}; -use http::{header, request::Parts, StatusCode}; +use axum_extra::{headers, TypedHeader}; +use http::StatusCode; use oauth2::{ basic::BasicClient, reqwest::async_http_client, AuthUrl, AuthorizationCode, ClientId, ClientSecret, CsrfToken, RedirectUrl, Scope, TokenResponse, TokenUrl, }; use serde::{Deserialize, Serialize}; -use std::{convert::Infallible, env}; +use std::{env, str::FromStr, time::Duration}; +use tower_sessions::{ + session::{Id, Record}, + CachingSessionStore, SessionStore, +}; +use tower_sessions_moka_store::MokaStore; +use tower_sessions_rusqlite_store::{tokio_rusqlite, RusqliteStore}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; -static COOKIE_NAME: &str = "SESSION"; -static CSRF_TOKEN: &str = "csrf_token"; +/// The cookie to store the session id for user information. +const SESSION_COOKIE: &str = "info"; +const SESSION_DATA_KEY: &str = "data"; + +/// The time a user can be logged in before needing to re-authenticate. +/// (24 * 3600 seconds = 1 day) +const SESSION_EXPIRATION: Duration = Duration::from_secs(24 * 3600); + +/// The cookie used to pass the CSRF token through discord auth. +const OAUTH_CSRF_COOKIE: &str = "SESSION"; +const CSRF_TOKEN: &str = "csrf_token"; + +/// The time we allow to re-direct to an authentication service then back to our +/// application (3600 seconds = 1 hour). +const OAUTH_SESSION_EXPIRATION: Duration = Duration::from_secs(3600); #[tokio::main] async fn main() { @@ -40,12 +58,23 @@ async fn main() { .with(tracing_subscriber::fmt::layer()) .init(); - // `MemoryStore` is just used as an example. Don't use this in production. - let store = MemoryStore::new(); + // Create session backing SQL database. + // While some monolithic application may use a local file in production to back their database, + // it is common that you would setup a connection to a remote service. You may need to change + // `conn` to suit your use-case. + let file = tempfile::NamedTempFile::new().unwrap(); + let conn = tokio_rusqlite::Connection::open(file.path()).await.unwrap(); + let sql_store = RusqliteStore::new(conn); + + // Create session in-memory cache. + let moka_store = MokaStore::new(Some(100)); + let store = CachingSessionStore::new(moka_store, sql_store); + + // Create app state. let oauth_client = oauth_client().unwrap(); let app_state = AppState { - store, oauth_client, + store, }; let app = Router::new() @@ -74,20 +103,8 @@ async fn main() { #[derive(Clone)] struct AppState { - store: MemoryStore, oauth_client: BasicClient, -} - -impl FromRef for MemoryStore { - fn from_ref(state: &AppState) -> Self { - state.store.clone() - } -} - -impl FromRef for BasicClient { - fn from_ref(state: &AppState) -> Self { - state.oauth_client.clone() - } + store: CachingSessionStore, } fn oauth_client() -> Result { @@ -132,40 +149,59 @@ struct User { } // Session is optional -async fn index(user: Option) -> impl IntoResponse { - match user { +async fn index( + State(AppState { store, .. }): State, + TypedHeader(cookies): TypedHeader, +) -> Result { + let session_id = Id::from_str( + cookies + .get(SESSION_COOKIE) + .context("missing session cookie")?, + ) + .unwrap(); + let session = store.load(&session_id).await.unwrap().unwrap(); + let user = session + .data + .get(SESSION_DATA_KEY) + .map(|v| serde_json::from_value::(v.clone()).unwrap()); + Ok(match user { Some(u) => format!( "Hey {}! You're logged in!\nYou may now access `/protected`.\nLog out with `/logout`.", u.username ), None => "You're not logged in.\nVisit `/auth/discord` to do so.".to_string(), - } + }) } async fn discord_auth( - State(client): State, - State(store): State, + State(AppState { + oauth_client, + store, + }): State, ) -> Result { - let (auth_url, csrf_token) = client + let (auth_url, csrf_token) = oauth_client .authorize_url(CsrfToken::new_random) .add_scope(Scope::new("identify".to_string())) .url(); - // Create session to store csrf_token - let mut session = Session::new(); - session - .insert(CSRF_TOKEN, &csrf_token) - .context("failed in inserting CSRF token into session")?; - - // Store the session in MemoryStore and retrieve the session cookie - let cookie = store - .store_session(session) + // Store the token in the session and retrieve the session cookie. + let session_id = Id(i128::from_le_bytes(uuid::Uuid::new_v4().to_bytes_le())); + store + .create(&mut Record { + id: session_id, + data: [( + CSRF_TOKEN.to_string(), + serde_json::to_value(csrf_token).unwrap(), + )] + .into(), + expiry_date: time::OffsetDateTime::now_utc() + OAUTH_SESSION_EXPIRATION, + }) .await - .context("failed to store CSRF token session")? - .context("unexpected error retrieving CSRF cookie value")?; + .context("failed in inserting CSRF token into session")?; // Attach the session cookie to the response header - let cookie = format!("{COOKIE_NAME}={cookie}; SameSite=Lax; HttpOnly; Secure; Path=/"); + let cookie = + format!("{OAUTH_CSRF_COOKIE}={session_id}; SameSite=Lax; HttpOnly; Secure; Path=/"); let mut headers = HeaderMap::new(); headers.insert( SET_COOKIE, @@ -176,30 +212,40 @@ async fn discord_auth( } // Valid user session required. If there is none, redirect to the auth page -async fn protected(user: User) -> impl IntoResponse { - format!("Welcome to the protected area :)\nHere's your info:\n{user:?}") +async fn protected( + State(AppState { store, .. }): State, + TypedHeader(cookies): TypedHeader, +) -> Result { + let session_id = Id::from_str( + cookies + .get(SESSION_COOKIE) + .context("missing session cookie")?, + ) + .unwrap(); + let session = store + .load(&session_id) + .await + .unwrap() + .context("missing session")?; + let user = serde_json::from_value::(session.data.get(SESSION_DATA_KEY).unwrap().clone()) + .unwrap(); + Ok(format!( + "Welcome to the protected area :)\nHere's your info:\n{user:?}" + )) } async fn logout( - State(store): State, + State(AppState { store, .. }): State, TypedHeader(cookies): TypedHeader, ) -> Result { - let cookie = cookies - .get(COOKIE_NAME) - .context("unexpected error getting cookie name")?; - - let session = match store - .load_session(cookie.to_string()) - .await - .context("failed to load session")? - { - Some(s) => s, - // No session active, just redirect - None => return Ok(Redirect::to("/")), - }; - + let session_id = Id::from_str( + cookies + .get(SESSION_COOKIE) + .context("missing session cookie")?, + ) + .unwrap(); store - .destroy_session(session) + .delete(&session_id) .await .context("failed to destroy session")?; @@ -215,39 +261,28 @@ struct AuthRequest { async fn csrf_token_validation_workflow( auth_request: &AuthRequest, - cookies: &headers::Cookie, - store: &MemoryStore, + store: &CachingSessionStore, + oauth_session_id: Id, ) -> Result<(), AppError> { - // Extract the cookie from the request - let cookie = cookies - .get(COOKIE_NAME) - .context("unexpected error getting cookie name")? - .to_string(); - - // Load the session - let session = match store - .load_session(cookie) - .await - .context("failed to load session")? - { - Some(session) => session, - None => return Err(anyhow!("Session not found").into()), - }; + let oauth_session = store.load(&oauth_session_id).await.unwrap().unwrap(); // Extract the CSRF token from the session - let stored_csrf_token = session - .get::(CSRF_TOKEN) + let csrf_token_serialized = oauth_session + .data + .get(CSRF_TOKEN) + .context("failed to get value from session")?; + let csrf_token = serde_json::from_value::(csrf_token_serialized.clone()) .context("CSRF token not found in session")? .to_owned(); // Cleanup the CSRF token session store - .destroy_session(session) + .delete(&oauth_session_id) .await .context("Failed to destroy old session")?; // Validate CSRF token is the same as the one in the auth request - if *stored_csrf_token.secret() != auth_request.state { + if *csrf_token.secret() != auth_request.state { return Err(anyhow!("CSRF token mismatch").into()); } @@ -255,12 +290,20 @@ async fn csrf_token_validation_workflow( } async fn login_authorized( - Query(query): Query, - State(store): State, - State(oauth_client): State, + State(AppState { + oauth_client, + store, + }): State, TypedHeader(cookies): TypedHeader, + Query(query): Query, ) -> Result { - csrf_token_validation_workflow(&query, &cookies, &store).await?; + let oauth_session_id = Id::from_str( + cookies + .get(OAUTH_CSRF_COOKIE) + .context("missing session cookie")?, + ) + .unwrap(); + csrf_token_validation_workflow(&query, &store, oauth_session_id).await?; // Get an auth token let token = oauth_client @@ -283,20 +326,22 @@ async fn login_authorized( .context("failed to deserialize response as JSON")?; // Create a new session filled with user data - let mut session = Session::new(); - session - .insert("user", &user_data) - .context("failed in inserting serialized value into session")?; - - // Store session and get corresponding cookie - let cookie = store - .store_session(session) + let session_id = Id(i128::from_le_bytes(uuid::Uuid::new_v4().to_bytes_le())); + store + .create(&mut Record { + id: session_id, + data: [( + SESSION_DATA_KEY.to_string(), + serde_json::to_value(user_data).unwrap(), + )] + .into(), + expiry_date: time::OffsetDateTime::now_utc() + SESSION_EXPIRATION, + }) .await - .context("failed to store session")? - .context("unexpected error retrieving cookie value")?; + .context("failed in inserting serialized value into session")?; - // Build the cookie - let cookie = format!("{COOKIE_NAME}={cookie}; SameSite=Lax; HttpOnly; Secure; Path=/"); + // Store session and get corresponding cookie. + let cookie = format!("{SESSION_COOKIE}={session_id}; SameSite=Lax; HttpOnly; Secure; Path=/"); // Set cookie let mut headers = HeaderMap::new(); @@ -308,67 +353,6 @@ async fn login_authorized( Ok((headers, Redirect::to("/"))) } -struct AuthRedirect; - -impl IntoResponse for AuthRedirect { - fn into_response(self) -> Response { - Redirect::temporary("/auth/discord").into_response() - } -} - -impl FromRequestParts for User -where - MemoryStore: FromRef, - S: Send + Sync, -{ - // If anything goes wrong or no session is found, redirect to the auth page - type Rejection = AuthRedirect; - - async fn from_request_parts(parts: &mut Parts, state: &S) -> Result { - let store = MemoryStore::from_ref(state); - - let cookies = parts - .extract::>() - .await - .map_err(|e| match *e.name() { - header::COOKIE => match e.reason() { - TypedHeaderRejectionReason::Missing => AuthRedirect, - _ => panic!("unexpected error getting Cookie header(s): {e}"), - }, - _ => panic!("unexpected error getting cookies: {e}"), - })?; - let session_cookie = cookies.get(COOKIE_NAME).ok_or(AuthRedirect)?; - - let session = store - .load_session(session_cookie.to_string()) - .await - .unwrap() - .ok_or(AuthRedirect)?; - - let user = session.get::("user").ok_or(AuthRedirect)?; - - Ok(user) - } -} - -impl OptionalFromRequestParts for User -where - MemoryStore: FromRef, - S: Send + Sync, -{ - type Rejection = Infallible; - - async fn from_request_parts( - parts: &mut Parts, - state: &S, - ) -> Result, Self::Rejection> { - match >::from_request_parts(parts, state).await { - Ok(res) => Ok(Some(res)), - Err(AuthRedirect) => Ok(None), - } - } -} - // Use anyhow, define error and enable '?' // For a simplified example of using anyhow in axum check /examples/anyhow-error-response #[derive(Debug)]