Rework browser sessions
This commit is contained in:
parent
950a493dc4
commit
66b2c51339
382
Cargo.lock
generated
382
Cargo.lock
generated
@ -17,166 +17,12 @@ version = "1.0.53"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0"
|
checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "arrayref"
|
|
||||||
version = "0.3.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "arrayvec"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.7.2"
|
version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-channel"
|
|
||||||
version = "1.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319"
|
|
||||||
dependencies = [
|
|
||||||
"concurrent-queue",
|
|
||||||
"event-listener",
|
|
||||||
"futures-core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-executor"
|
|
||||||
version = "1.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965"
|
|
||||||
dependencies = [
|
|
||||||
"async-task",
|
|
||||||
"concurrent-queue",
|
|
||||||
"fastrand",
|
|
||||||
"futures-lite",
|
|
||||||
"once_cell",
|
|
||||||
"slab",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-global-executor"
|
|
||||||
version = "2.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6"
|
|
||||||
dependencies = [
|
|
||||||
"async-channel",
|
|
||||||
"async-executor",
|
|
||||||
"async-io",
|
|
||||||
"async-mutex",
|
|
||||||
"blocking",
|
|
||||||
"futures-lite",
|
|
||||||
"num_cpus",
|
|
||||||
"once_cell",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-io"
|
|
||||||
version = "1.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b"
|
|
||||||
dependencies = [
|
|
||||||
"concurrent-queue",
|
|
||||||
"futures-lite",
|
|
||||||
"libc",
|
|
||||||
"log",
|
|
||||||
"once_cell",
|
|
||||||
"parking",
|
|
||||||
"polling",
|
|
||||||
"slab",
|
|
||||||
"socket2",
|
|
||||||
"waker-fn",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-lock"
|
|
||||||
version = "2.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b"
|
|
||||||
dependencies = [
|
|
||||||
"event-listener",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-mutex"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e"
|
|
||||||
dependencies = [
|
|
||||||
"event-listener",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-redis-session"
|
|
||||||
version = "0.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ba82ce101e6cde598074604ef4a882bdd6b3a283baff446ae73ae2727c242452"
|
|
||||||
dependencies = [
|
|
||||||
"async-session",
|
|
||||||
"redis 0.20.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-session"
|
|
||||||
version = "3.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "07da4ce523b4e2ebaaf330746761df23a465b951a83d84bbce4233dabedae630"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"async-lock",
|
|
||||||
"async-trait",
|
|
||||||
"base64",
|
|
||||||
"bincode",
|
|
||||||
"blake3",
|
|
||||||
"chrono",
|
|
||||||
"hmac",
|
|
||||||
"log",
|
|
||||||
"rand",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"sha2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-std"
|
|
||||||
version = "1.10.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f8056f1455169ab86dd47b47391e4ab0cbd25410a70e9fe675544f49bafaf952"
|
|
||||||
dependencies = [
|
|
||||||
"async-channel",
|
|
||||||
"async-global-executor",
|
|
||||||
"async-io",
|
|
||||||
"async-lock",
|
|
||||||
"crossbeam-utils",
|
|
||||||
"futures-channel",
|
|
||||||
"futures-core",
|
|
||||||
"futures-io",
|
|
||||||
"futures-lite",
|
|
||||||
"gloo-timers",
|
|
||||||
"kv-log-macro",
|
|
||||||
"log",
|
|
||||||
"memchr",
|
|
||||||
"num_cpus",
|
|
||||||
"once_cell",
|
|
||||||
"pin-project-lite",
|
|
||||||
"pin-utils",
|
|
||||||
"slab",
|
|
||||||
"wasm-bindgen-futures",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-task"
|
|
||||||
version = "4.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "677d306121baf53310a3fd342d88dc0824f6bbeace68347593658525565abee8"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.52"
|
version = "0.1.52"
|
||||||
@ -208,12 +54,6 @@ dependencies = [
|
|||||||
"autocfg 1.1.0",
|
"autocfg 1.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "atomic-waker"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "auto_impl"
|
name = "auto_impl"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@ -326,7 +166,7 @@ checksum = "c440295545cb69b3cec992ae8844fbb1de1c84f2f90248438af287e14bb09bde"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bb8",
|
"bb8",
|
||||||
"redis 0.21.5",
|
"redis",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -356,21 +196,6 @@ dependencies = [
|
|||||||
"wyz",
|
"wyz",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "blake3"
|
|
||||||
version = "0.3.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3"
|
|
||||||
dependencies = [
|
|
||||||
"arrayref",
|
|
||||||
"arrayvec 0.5.2",
|
|
||||||
"cc",
|
|
||||||
"cfg-if 0.1.10",
|
|
||||||
"constant_time_eq",
|
|
||||||
"crypto-mac 0.8.0",
|
|
||||||
"digest",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -387,20 +212,6 @@ version = "0.2.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
|
checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "blocking"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "046e47d4b2d391b1f6f8b407b1deb8dee56c1852ccd868becf2710f601b5f427"
|
|
||||||
dependencies = [
|
|
||||||
"async-channel",
|
|
||||||
"async-task",
|
|
||||||
"atomic-waker",
|
|
||||||
"fastrand",
|
|
||||||
"futures-lite",
|
|
||||||
"once_cell",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.9.1"
|
version = "3.9.1"
|
||||||
@ -428,12 +239,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cache-padded"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.72"
|
version = "1.0.72"
|
||||||
@ -504,15 +309,6 @@ dependencies = [
|
|||||||
"tokio-util",
|
"tokio-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "concurrent-queue"
|
|
||||||
version = "1.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
|
|
||||||
dependencies = [
|
|
||||||
"cache-padded",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "console_error_panic_hook"
|
name = "console_error_panic_hook"
|
||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
@ -535,12 +331,6 @@ version = "0.7.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
|
checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "constant_time_eq"
|
|
||||||
version = "0.1.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cookie"
|
name = "cookie"
|
||||||
version = "0.16.0"
|
version = "0.16.0"
|
||||||
@ -576,16 +366,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crossbeam-utils"
|
|
||||||
version = "0.8.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if 1.0.0",
|
|
||||||
"lazy_static",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crunchy"
|
name = "crunchy"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@ -616,16 +396,6 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[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]]
|
[[package]]
|
||||||
name = "crypto-mac"
|
name = "crypto-mac"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
@ -636,16 +406,6 @@ dependencies = [
|
|||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ctor"
|
|
||||||
version = "0.1.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa"
|
|
||||||
dependencies = [
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "der"
|
name = "der"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
@ -794,7 +554,7 @@ version = "0.6.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f15e1a2a54bc6bc3f8ea94afafbb374264f8322fcacdae06fefda80a206739ac"
|
checksum = "f15e1a2a54bc6bc3f8ea94afafbb374264f8322fcacdae06fefda80a206739ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec 0.7.2",
|
"arrayvec",
|
||||||
"bytes",
|
"bytes",
|
||||||
"ecdsa",
|
"ecdsa",
|
||||||
"elliptic-curve 0.11.12",
|
"elliptic-curve 0.11.12",
|
||||||
@ -846,21 +606,6 @@ dependencies = [
|
|||||||
"ws_stream_wasm",
|
"ws_stream_wasm",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "event-listener"
|
|
||||||
version = "2.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fastrand"
|
|
||||||
version = "1.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
|
|
||||||
dependencies = [
|
|
||||||
"instant",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ff"
|
name = "ff"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
@ -967,21 +712,6 @@ version = "0.3.21"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
|
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-lite"
|
|
||||||
version = "1.12.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48"
|
|
||||||
dependencies = [
|
|
||||||
"fastrand",
|
|
||||||
"futures-core",
|
|
||||||
"futures-io",
|
|
||||||
"memchr",
|
|
||||||
"parking",
|
|
||||||
"pin-project-lite",
|
|
||||||
"waker-fn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.21"
|
version = "0.3.21"
|
||||||
@ -1052,18 +782,6 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "gloo-timers"
|
|
||||||
version = "0.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4d12a7f4e95cfe710f1d624fb1210b7d961a5fb05c4fd942f4feab06e61f590e"
|
|
||||||
dependencies = [
|
|
||||||
"futures-channel",
|
|
||||||
"futures-core",
|
|
||||||
"js-sys",
|
|
||||||
"wasm-bindgen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "group"
|
name = "group"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
@ -1146,7 +864,7 @@ version = "0.11.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
|
checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crypto-mac 0.11.1",
|
"crypto-mac",
|
||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1368,15 +1086,6 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7"
|
checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "kv-log-macro"
|
|
||||||
version = "1.0.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
|
|
||||||
dependencies = [
|
|
||||||
"log",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@ -1414,7 +1123,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"value-bag",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1697,7 +1405,7 @@ version = "2.3.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "373b1a4c1338d9cd3d1fa53b3a11bdab5ab6bd80a20f7f7becd76953ae2be909"
|
checksum = "373b1a4c1338d9cd3d1fa53b3a11bdab5ab6bd80a20f7f7becd76953ae2be909"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec 0.7.2",
|
"arrayvec",
|
||||||
"bitvec",
|
"bitvec",
|
||||||
"byte-slice-cast",
|
"byte-slice-cast",
|
||||||
"impl-trait-for-tuples",
|
"impl-trait-for-tuples",
|
||||||
@ -1717,12 +1425,6 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
@ -1911,19 +1613,6 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "polling"
|
|
||||||
version = "2.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if 1.0.0",
|
|
||||||
"libc",
|
|
||||||
"log",
|
|
||||||
"wepoll-ffi",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
@ -2054,27 +1743,6 @@ dependencies = [
|
|||||||
"rand_core",
|
"rand_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "redis"
|
|
||||||
version = "0.20.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d4f0ceb2ec0dd769483ecd283f6615aa83dcd0be556d5294c6e659caefe7cc54"
|
|
||||||
dependencies = [
|
|
||||||
"async-std",
|
|
||||||
"async-trait",
|
|
||||||
"bytes",
|
|
||||||
"combine",
|
|
||||||
"dtoa",
|
|
||||||
"futures-util",
|
|
||||||
"itoa 0.4.8",
|
|
||||||
"percent-encoding",
|
|
||||||
"pin-project-lite",
|
|
||||||
"sha1",
|
|
||||||
"tokio",
|
|
||||||
"tokio-util",
|
|
||||||
"url",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redis"
|
name = "redis"
|
||||||
version = "0.21.5"
|
version = "0.21.5"
|
||||||
@ -2447,21 +2115,6 @@ dependencies = [
|
|||||||
"opaque-debug",
|
"opaque-debug",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sha1"
|
|
||||||
version = "0.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770"
|
|
||||||
dependencies = [
|
|
||||||
"sha1_smol",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sha1_smol"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.9.9"
|
version = "0.9.9"
|
||||||
@ -2543,8 +2196,6 @@ name = "siwe-oidc"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-redis-session",
|
|
||||||
"async-session",
|
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum",
|
"axum",
|
||||||
"bb8-redis",
|
"bb8-redis",
|
||||||
@ -3108,28 +2759,12 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "value-bag"
|
|
||||||
version = "1.0.0-alpha.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "79923f7731dc61ebfba3633098bf3ac533bbd35ccd8c57e7088d9a5eebe0263f"
|
|
||||||
dependencies = [
|
|
||||||
"ctor",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "waker-fn"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "want"
|
name = "want"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -3289,15 +2924,6 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wepoll-ffi"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@ -35,7 +35,6 @@ ethers-providers = "0.6.2"
|
|||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
|
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
async-session = "3.0.0"
|
|
||||||
axum = { version = "0.4.3", features = ["headers"] }
|
axum = { version = "0.4.3", features = ["headers"] }
|
||||||
# axum-debug = "0.3.2"
|
# axum-debug = "0.3.2"
|
||||||
chrono = "0.4.19"
|
chrono = "0.4.19"
|
||||||
@ -44,7 +43,6 @@ tokio = { version = "1.14.0", features = ["full"] }
|
|||||||
tower-http = { version = "0.2.0", features = ["fs", "trace", "cors"] }
|
tower-http = { version = "0.2.0", features = ["fs", "trace", "cors"] }
|
||||||
tracing-subscriber = { version = "0.3.2", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.2", features = ["env-filter"] }
|
||||||
bb8-redis = "0.10.1"
|
bb8-redis = "0.10.1"
|
||||||
async-redis-session = "0.2.2"
|
|
||||||
uuid = { version = "0.8", features = ["serde", "v4"] }
|
uuid = { version = "0.8", features = ["serde", "v4"] }
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
|
110
src/axum_lib.rs
110
src/axum_lib.rs
@ -1,5 +1,4 @@
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use async_redis_session::RedisSessionStore;
|
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::{self, Extension, Form, Path, Query, TypedHeader},
|
extract::{self, Extension, Form, Path, Query, TypedHeader},
|
||||||
http::{
|
http::{
|
||||||
@ -22,7 +21,7 @@ use headers::{
|
|||||||
};
|
};
|
||||||
use openidconnect::core::{
|
use openidconnect::core::{
|
||||||
CoreClientMetadata, CoreClientRegistrationResponse, CoreJsonWebKeySet, CoreProviderMetadata,
|
CoreClientMetadata, CoreClientRegistrationResponse, CoreJsonWebKeySet, CoreProviderMetadata,
|
||||||
CoreResponseType, CoreTokenResponse, CoreUserInfoClaims, CoreUserInfoJsonWebToken,
|
CoreTokenResponse, CoreUserInfoClaims, CoreUserInfoJsonWebToken,
|
||||||
};
|
};
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
use rsa::{
|
use rsa::{
|
||||||
@ -38,7 +37,6 @@ use tracing::info;
|
|||||||
|
|
||||||
use super::config;
|
use super::config;
|
||||||
use super::oidc::{self, CustomError};
|
use super::oidc::{self, CustomError};
|
||||||
use super::session::*;
|
|
||||||
use ::siwe_oidc::db::*;
|
use ::siwe_oidc::db::*;
|
||||||
|
|
||||||
impl IntoResponse for CustomError {
|
impl IntoResponse for CustomError {
|
||||||
@ -82,14 +80,6 @@ async fn provider_metadata(
|
|||||||
Ok(oidc::metadata(config.base_url)?.into())
|
Ok(oidc::metadata(config.base_url)?.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO should check Authorization header
|
|
||||||
// Actually, client secret can be
|
|
||||||
// 1. in the POST (currently supported) [x]
|
|
||||||
// 2. Authorization header [x]
|
|
||||||
// 3. JWT [ ]
|
|
||||||
// 4. signed JWT [ ]
|
|
||||||
// according to Keycloak
|
|
||||||
|
|
||||||
async fn token(
|
async fn token(
|
||||||
Form(form): Form<oidc::TokenForm>,
|
Form(form): Form<oidc::TokenForm>,
|
||||||
bearer: Option<TypedHeader<Authorization<Bearer>>>,
|
bearer: Option<TypedHeader<Authorization<Bearer>>>,
|
||||||
@ -116,43 +106,16 @@ async fn token(
|
|||||||
Ok(token_response.into())
|
Ok(token_response.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO handle `registration` parameter
|
|
||||||
async fn authorize(
|
async fn authorize(
|
||||||
session: UserSessionFromSession,
|
|
||||||
Query(params): Query<oidc::AuthorizeParams>,
|
Query(params): Query<oidc::AuthorizeParams>,
|
||||||
Extension(redis_client): Extension<RedisClient>,
|
Extension(redis_client): Extension<RedisClient>,
|
||||||
) -> Result<(HeaderMap, Redirect), CustomError> {
|
) -> Result<(HeaderMap, Redirect), CustomError> {
|
||||||
let (nonce, headers) = match session {
|
let (url, session_cookie) = oidc::authorize(params, &redis_client).await?;
|
||||||
UserSessionFromSession::Found(nonce) => (nonce, HeaderMap::new()),
|
let mut headers = HeaderMap::new();
|
||||||
UserSessionFromSession::Invalid(cookie) => {
|
headers.insert(
|
||||||
let mut headers = HeaderMap::new();
|
header::SET_COOKIE,
|
||||||
headers.insert(header::SET_COOKIE, cookie);
|
session_cookie.to_string().parse().unwrap(),
|
||||||
return Ok((
|
);
|
||||||
headers,
|
|
||||||
Redirect::to(
|
|
||||||
format!(
|
|
||||||
"/authorize?client_id={}&redirect_uri={}&scope={}&response_type={}&state={}&client_id={}{}",
|
|
||||||
¶ms.client_id,
|
|
||||||
¶ms.redirect_uri.to_string(),
|
|
||||||
¶ms.scope.to_string(),
|
|
||||||
¶ms.response_type.unwrap_or(CoreResponseType::Code).as_ref(),
|
|
||||||
¶ms.state.unwrap_or_default(),
|
|
||||||
¶ms.client_id,
|
|
||||||
¶ms.nonce.map(|n| format!("&nonce={}", n.secret())).unwrap_or_default()
|
|
||||||
)
|
|
||||||
.parse()
|
|
||||||
.map_err(|e| anyhow!("Could not parse URI: {}", e))?,
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
UserSessionFromSession::Created { header, nonce } => {
|
|
||||||
let mut headers = HeaderMap::new();
|
|
||||||
headers.insert(header::SET_COOKIE, header);
|
|
||||||
(nonce, headers)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let url = oidc::authorize(params, nonce, &redis_client).await?;
|
|
||||||
Ok((
|
Ok((
|
||||||
headers,
|
headers,
|
||||||
Redirect::to(
|
Redirect::to(
|
||||||
@ -164,58 +127,16 @@ async fn authorize(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn sign_in(
|
async fn sign_in(
|
||||||
session: UserSessionFromSession,
|
|
||||||
Query(params): Query<oidc::SignInParams>,
|
Query(params): Query<oidc::SignInParams>,
|
||||||
TypedHeader(cookies): TypedHeader<headers::Cookie>,
|
TypedHeader(cookies): TypedHeader<headers::Cookie>,
|
||||||
Extension(redis_client): Extension<RedisClient>,
|
Extension(redis_client): Extension<RedisClient>,
|
||||||
) -> Result<(HeaderMap, Redirect), CustomError> {
|
) -> Result<Redirect, CustomError> {
|
||||||
let (nonce, headers) = match session {
|
let url = oidc::sign_in(params, cookies, &redis_client).await?;
|
||||||
UserSessionFromSession::Found(nonce) => (nonce, HeaderMap::new()),
|
Ok(Redirect::to(
|
||||||
UserSessionFromSession::Invalid(header) => {
|
url.as_str()
|
||||||
let mut headers = HeaderMap::new();
|
.parse()
|
||||||
headers.insert(header::SET_COOKIE, header);
|
.map_err(|e| anyhow!("Could not parse URI: {}", e))?,
|
||||||
return Ok((
|
|
||||||
headers,
|
|
||||||
Redirect::to(
|
|
||||||
format!(
|
|
||||||
"/authorize?client_id={}&redirect_uri={}&scope=openid&response_type=code&state={}",
|
|
||||||
¶ms.client_id.clone(),
|
|
||||||
¶ms.redirect_uri.to_string(),
|
|
||||||
¶ms.state,
|
|
||||||
)
|
|
||||||
.parse()
|
|
||||||
.map_err(|e| anyhow!("Could not parse URI: {}", e))?,
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
UserSessionFromSession::Created { .. } => {
|
|
||||||
return Ok((
|
|
||||||
HeaderMap::new(),
|
|
||||||
Redirect::to(
|
|
||||||
format!(
|
|
||||||
"/authorize?client_id={}&redirect_uri={}&scope=openid&response_type=code&state={}",
|
|
||||||
¶ms.client_id.clone(),
|
|
||||||
¶ms.redirect_uri.to_string(),
|
|
||||||
¶ms.state,
|
|
||||||
)
|
|
||||||
.parse()
|
|
||||||
.map_err(|e| anyhow!("Could not parse URI: {}", e))?,
|
|
||||||
),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let url = oidc::sign_in(params, Some(nonce), cookies, &redis_client).await?;
|
|
||||||
|
|
||||||
Ok((
|
|
||||||
headers,
|
|
||||||
Redirect::to(
|
|
||||||
url.as_str()
|
|
||||||
.parse()
|
|
||||||
.map_err(|e| anyhow!("Could not parse URI: {}", e))?,
|
|
||||||
),
|
|
||||||
))
|
))
|
||||||
// TODO clear session
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn register(
|
async fn register(
|
||||||
@ -434,11 +355,6 @@ pub async fn main() {
|
|||||||
.layer(AddExtensionLayer::new(private_key))
|
.layer(AddExtensionLayer::new(private_key))
|
||||||
.layer(AddExtensionLayer::new(config.clone()))
|
.layer(AddExtensionLayer::new(config.clone()))
|
||||||
.layer(AddExtensionLayer::new(redis_client))
|
.layer(AddExtensionLayer::new(redis_client))
|
||||||
.layer(AddExtensionLayer::new(
|
|
||||||
RedisSessionStore::new(config.redis_url.clone())
|
|
||||||
.unwrap()
|
|
||||||
.with_prefix("async-sessions/"),
|
|
||||||
))
|
|
||||||
.layer(TraceLayer::new_for_http());
|
.layer(TraceLayer::new_for_http());
|
||||||
|
|
||||||
let addr = SocketAddr::from((config.address, config.port));
|
let addr = SocketAddr::from((config.address, config.port));
|
||||||
|
30
src/db/cf.rs
30
src/db/cf.rs
@ -1,6 +1,5 @@
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
// use cached::{stores::TimedCache, Cached};
|
|
||||||
use chrono::{DateTime, Duration, Utc};
|
use chrono::{DateTime, Duration, Utc};
|
||||||
use matchit::Node;
|
use matchit::Node;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@ -109,7 +108,6 @@ impl DBClient for CFClient {
|
|||||||
.map_err(|e| anyhow!("Failed to serialize client entry: {}", e))?,
|
.map_err(|e| anyhow!("Failed to serialize client entry: {}", e))?,
|
||||||
)
|
)
|
||||||
.map_err(|e| anyhow!("Failed to build KV put: {}", e))?
|
.map_err(|e| anyhow!("Failed to build KV put: {}", e))?
|
||||||
// TODO put some sort of expiration for dynamic registration
|
|
||||||
.execute()
|
.execute()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| anyhow!("Failed to put KV: {}", e))?;
|
.map_err(|e| anyhow!("Failed to put KV: {}", e))?;
|
||||||
@ -202,4 +200,32 @@ impl DBClient for CFClient {
|
|||||||
code => Err(anyhow!("Error fetching from Durable Object: {}", code)),
|
code => Err(anyhow!("Error fetching from Durable Object: {}", code)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn set_session(&self, id: String, entry: SessionEntry) -> Result<()> {
|
||||||
|
self.ctx
|
||||||
|
.kv(KV_NAMESPACE)
|
||||||
|
.map_err(|e| anyhow!("Failed to get KV store: {}", e))?
|
||||||
|
.put(
|
||||||
|
&format!("{}/{}", KV_SESSION_PREFIX, id),
|
||||||
|
serde_json::to_string(&entry)
|
||||||
|
.map_err(|e| anyhow!("Failed to serialize client entry: {}", e))?,
|
||||||
|
)
|
||||||
|
.map_err(|e| anyhow!("Failed to build KV put: {}", e))?
|
||||||
|
.expiration_ttl(SESSION_LIFETIME)
|
||||||
|
.execute()
|
||||||
|
.await
|
||||||
|
.map_err(|e| anyhow!("Failed to put KV: {}", e))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_session(&self, id: String) -> Result<Option<SessionEntry>> {
|
||||||
|
Ok(self
|
||||||
|
.ctx
|
||||||
|
.kv(KV_NAMESPACE)
|
||||||
|
.map_err(|e| anyhow!("Failed to get KV store: {}", e))?
|
||||||
|
.get(&format!("{}/{}", KV_SESSION_PREFIX, id))
|
||||||
|
.json()
|
||||||
|
.await
|
||||||
|
.map_err(|e| anyhow!("Failed to get KV: {}", e))?)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,10 @@ mod cf;
|
|||||||
pub use cf::CFClient;
|
pub use cf::CFClient;
|
||||||
|
|
||||||
const KV_CLIENT_PREFIX: &str = "clients";
|
const KV_CLIENT_PREFIX: &str = "clients";
|
||||||
|
const KV_SESSION_PREFIX: &str = "sessions";
|
||||||
pub const ENTRY_LIFETIME: usize = 30;
|
pub const ENTRY_LIFETIME: usize = 30;
|
||||||
|
pub const SESSION_LIFETIME: u64 = 300; // 5min
|
||||||
|
pub const SESSION_COOKIE_NAME: &str = "session";
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
pub struct CodeEntry {
|
pub struct CodeEntry {
|
||||||
@ -33,6 +36,14 @@ pub struct ClientEntry {
|
|||||||
pub access_token: Option<RegistrationAccessToken>,
|
pub access_token: Option<RegistrationAccessToken>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
pub struct SessionEntry {
|
||||||
|
pub siwe_nonce: String,
|
||||||
|
pub oidc_nonce: Option<Nonce>,
|
||||||
|
pub secret: String,
|
||||||
|
pub signin_count: u64,
|
||||||
|
}
|
||||||
|
|
||||||
// Using a trait to easily pass async functions with async_trait
|
// Using a trait to easily pass async functions with async_trait
|
||||||
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
|
||||||
@ -42,4 +53,6 @@ pub trait DBClient {
|
|||||||
async fn delete_client(&self, client_id: String) -> Result<()>;
|
async fn delete_client(&self, client_id: String) -> Result<()>;
|
||||||
async fn set_code(&self, code: String, code_entry: CodeEntry) -> Result<()>;
|
async fn set_code(&self, code: String, code_entry: CodeEntry) -> Result<()>;
|
||||||
async fn get_code(&self, code: String) -> Result<Option<CodeEntry>>;
|
async fn get_code(&self, code: String) -> Result<Option<CodeEntry>>;
|
||||||
|
async fn set_session(&self, id: String, entry: SessionEntry) -> Result<()>;
|
||||||
|
async fn get_session(&self, id: String) -> Result<Option<SessionEntry>>;
|
||||||
}
|
}
|
||||||
|
@ -98,4 +98,40 @@ impl DBClient for RedisClient {
|
|||||||
.map_err(|e| anyhow!("Failed to deserialize code: {}", e))?;
|
.map_err(|e| anyhow!("Failed to deserialize code: {}", e))?;
|
||||||
Ok(Some(code_entry))
|
Ok(Some(code_entry))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn set_session(&self, id: String, entry: SessionEntry) -> Result<()> {
|
||||||
|
let mut conn = self
|
||||||
|
.pool
|
||||||
|
.get()
|
||||||
|
.await
|
||||||
|
.map_err(|e| anyhow!("Failed to get connection to database: {}", e))?;
|
||||||
|
|
||||||
|
conn.set_ex(
|
||||||
|
format!("{}/{}", KV_SESSION_PREFIX, id),
|
||||||
|
serde_json::to_string(&entry)
|
||||||
|
.map_err(|e| anyhow!("Failed to serialize session entry: {}", e))?,
|
||||||
|
SESSION_LIFETIME.try_into().unwrap(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|e| anyhow!("Failed to set kv: {}", e))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_session(&self, id: String) -> Result<Option<SessionEntry>> {
|
||||||
|
let mut conn = self
|
||||||
|
.pool
|
||||||
|
.get()
|
||||||
|
.await
|
||||||
|
.map_err(|e| anyhow!("Failed to get connection to database: {}", e))?;
|
||||||
|
let entry: Option<String> = conn
|
||||||
|
.get(format!("{}/{}", KV_SESSION_PREFIX, id))
|
||||||
|
.await
|
||||||
|
.map_err(|e| anyhow!("Failed to get kv: {}", e))?;
|
||||||
|
if let Some(e) = entry {
|
||||||
|
Ok(serde_json::from_str(&e)
|
||||||
|
.map_err(|e| anyhow!("Failed to deserialize session entry: {}", e))?)
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,6 @@ mod config;
|
|||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
mod oidc;
|
mod oidc;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
mod session;
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
use axum_lib::main as axum_main;
|
use axum_lib::main as axum_main;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
75
src/oidc.rs
75
src/oidc.rs
@ -1,5 +1,6 @@
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use chrono::{Duration, Utc};
|
use chrono::{Duration, Utc};
|
||||||
|
use cookie::Cookie;
|
||||||
use ethers_core::{types::H160, utils::to_checksum};
|
use ethers_core::{types::H160, utils::to_checksum};
|
||||||
use headers::{self, authorization::Bearer};
|
use headers::{self, authorization::Bearer};
|
||||||
use hex::FromHex;
|
use hex::FromHex;
|
||||||
@ -315,9 +316,8 @@ pub struct AuthorizeParams {
|
|||||||
|
|
||||||
pub async fn authorize(
|
pub async fn authorize(
|
||||||
params: AuthorizeParams,
|
params: AuthorizeParams,
|
||||||
nonce: String,
|
|
||||||
db_client: &DBClientType,
|
db_client: &DBClientType,
|
||||||
) -> Result<String, CustomError> {
|
) -> Result<(String, Box<Cookie<'_>>), CustomError> {
|
||||||
let client_entry = db_client
|
let client_entry = db_client
|
||||||
.get_client(params.client_id.clone())
|
.get_client(params.client_id.clone())
|
||||||
.await
|
.await
|
||||||
@ -328,6 +328,12 @@ pub async fn authorize(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let nonce: String = rand::thread_rng()
|
||||||
|
.sample_iter(&Alphanumeric)
|
||||||
|
.take(16)
|
||||||
|
.map(char::from)
|
||||||
|
.collect();
|
||||||
|
|
||||||
let mut r_u = params.redirect_uri.clone().url().clone();
|
let mut r_u = params.redirect_uri.clone().url().clone();
|
||||||
r_u.set_query(None);
|
r_u.set_query(None);
|
||||||
let mut r_us: Vec<Url> = client_entry
|
let mut r_us: Vec<Url> = client_entry
|
||||||
@ -397,15 +403,45 @@ pub async fn authorize(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let session_id = Uuid::new_v4();
|
||||||
|
let session_secret: String = rand::thread_rng()
|
||||||
|
.sample_iter(&Alphanumeric)
|
||||||
|
.take(16)
|
||||||
|
.map(char::from)
|
||||||
|
.collect();
|
||||||
|
db_client
|
||||||
|
.set_session(
|
||||||
|
session_id.to_string(),
|
||||||
|
SessionEntry {
|
||||||
|
siwe_nonce: nonce.clone(),
|
||||||
|
oidc_nonce: params.nonce.clone(),
|
||||||
|
secret: session_secret.clone(),
|
||||||
|
signin_count: 0,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
let session_cookie = Cookie::build(SESSION_COOKIE_NAME, session_id.to_string())
|
||||||
|
// .domain(base)
|
||||||
|
// .path("/")
|
||||||
|
.secure(true)
|
||||||
|
.http_only(true)
|
||||||
|
.max_age(cookie::time::Duration::seconds(
|
||||||
|
SESSION_LIFETIME.try_into().unwrap(),
|
||||||
|
))
|
||||||
|
.finish();
|
||||||
|
|
||||||
let domain = params.redirect_uri.url().host().unwrap();
|
let domain = params.redirect_uri.url().host().unwrap();
|
||||||
let oidc_nonce_param = if let Some(n) = ¶ms.nonce {
|
let oidc_nonce_param = if let Some(n) = ¶ms.nonce {
|
||||||
format!("&oidc_nonce={}", n.secret())
|
format!("&oidc_nonce={}", n.secret())
|
||||||
} else {
|
} else {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
};
|
};
|
||||||
Ok(format!(
|
Ok((
|
||||||
"/?nonce={}&domain={}&redirect_uri={}&state={}&client_id={}{}",
|
format!(
|
||||||
nonce, domain, *params.redirect_uri, state, params.client_id, oidc_nonce_param
|
"/?nonce={}&domain={}&redirect_uri={}&state={}&client_id={}{}",
|
||||||
|
nonce, domain, *params.redirect_uri, state, params.client_id, oidc_nonce_param
|
||||||
|
),
|
||||||
|
Box::new(session_cookie),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,10 +503,29 @@ pub struct SignInParams {
|
|||||||
|
|
||||||
pub async fn sign_in(
|
pub async fn sign_in(
|
||||||
params: SignInParams,
|
params: SignInParams,
|
||||||
expected_nonce: Option<String>,
|
// cookies_header: String,
|
||||||
cookies: headers::Cookie,
|
cookies: headers::Cookie,
|
||||||
db_client: &DBClientType,
|
db_client: &DBClientType,
|
||||||
) -> Result<Url, CustomError> {
|
) -> Result<Url, CustomError> {
|
||||||
|
// TODO redirect on session errors
|
||||||
|
let session_id = if let Some(c) = cookies.get(SESSION_COOKIE_NAME) {
|
||||||
|
c
|
||||||
|
} else {
|
||||||
|
return Err(CustomError::BadRequest(
|
||||||
|
"Session cookie not found".to_string(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
let session_entry = if let Some(e) = db_client.get_session(session_id.to_string()).await? {
|
||||||
|
e
|
||||||
|
} else {
|
||||||
|
return Err(CustomError::BadRequest("Session not found".to_string()));
|
||||||
|
};
|
||||||
|
if session_entry.signin_count > 0 {
|
||||||
|
return Err(CustomError::BadRequest(
|
||||||
|
"Session has already logged in".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let siwe_cookie: SiweCookie = match cookies.get(SIWE_COOKIE_KEY) {
|
let siwe_cookie: SiweCookie = match cookies.get(SIWE_COOKIE_KEY) {
|
||||||
Some(c) => serde_json::from_str(
|
Some(c) => serde_json::from_str(
|
||||||
&decode(c).map_err(|e| anyhow!("Could not decode siwe cookie: {}", e))?,
|
&decode(c).map_err(|e| anyhow!("Could not decode siwe cookie: {}", e))?,
|
||||||
@ -508,7 +563,7 @@ pub async fn sign_in(
|
|||||||
if domain.to_string() != *siwe_cookie.message.resources.get(0).unwrap().to_string() {
|
if domain.to_string() != *siwe_cookie.message.resources.get(0).unwrap().to_string() {
|
||||||
return Err(anyhow!("Conflicting domains in message and redirect").into());
|
return Err(anyhow!("Conflicting domains in message and redirect").into());
|
||||||
}
|
}
|
||||||
if expected_nonce.is_some() && expected_nonce.unwrap() != siwe_cookie.message.nonce {
|
if session_entry.siwe_nonce != siwe_cookie.message.nonce {
|
||||||
return Err(anyhow!("Conflicting nonces in message and session").into());
|
return Err(anyhow!("Conflicting nonces in message and session").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,6 +575,12 @@ pub async fn sign_in(
|
|||||||
auth_time: Utc::now(),
|
auth_time: Utc::now(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut new_session_entry = session_entry.clone();
|
||||||
|
new_session_entry.signin_count += 1;
|
||||||
|
db_client
|
||||||
|
.set_session(session_id.to_string(), new_session_entry)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let code = Uuid::new_v4();
|
let code = Uuid::new_v4();
|
||||||
db_client.set_code(code.to_string(), code_entry).await?;
|
db_client.set_code(code.to_string(), code_entry).await?;
|
||||||
|
|
||||||
|
119
src/session.rs
119
src/session.rs
@ -1,119 +0,0 @@
|
|||||||
use async_redis_session::RedisSessionStore;
|
|
||||||
use async_session::{Session, SessionStore as _};
|
|
||||||
use axum::{
|
|
||||||
async_trait,
|
|
||||||
extract::{Extension, FromRequest, RequestParts},
|
|
||||||
http::{self, header::HeaderValue, StatusCode},
|
|
||||||
};
|
|
||||||
use cookie::Cookie;
|
|
||||||
use rand::{distributions::Alphanumeric, Rng};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use tracing::debug;
|
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
const SESSION_COOKIE_NAME: &str = "session";
|
|
||||||
const SESSION_KEY: &str = "user_session";
|
|
||||||
|
|
||||||
pub enum UserSessionFromSession {
|
|
||||||
Found(String),
|
|
||||||
Created { header: HeaderValue, nonce: String },
|
|
||||||
Invalid(HeaderValue),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl<B> FromRequest<B> for UserSessionFromSession
|
|
||||||
where
|
|
||||||
B: Send,
|
|
||||||
{
|
|
||||||
type Rejection = (StatusCode, String);
|
|
||||||
|
|
||||||
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
|
|
||||||
let Extension(store) = match Extension::<RedisSessionStore>::from_request(req).await {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(e) => {
|
|
||||||
return Err((
|
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
format!("`MemoryStore` extension missing: {}", e),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let headers = if let Some(h) = req.headers() {
|
|
||||||
h
|
|
||||||
} else {
|
|
||||||
return Err((
|
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
"other extractor taken headers".to_string(),
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
let session_cookie: Cookie = if let Some(session_cookie) = headers
|
|
||||||
.get(http::header::COOKIE)
|
|
||||||
.and_then(|value| value.to_str().ok())
|
|
||||||
.map(|header| {
|
|
||||||
header
|
|
||||||
.split(';')
|
|
||||||
.map(|cookie| Cookie::parse(cookie).ok())
|
|
||||||
.find(|cookie| {
|
|
||||||
cookie.is_some() && cookie.as_ref().unwrap().name() == SESSION_COOKIE_NAME
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.flatten()
|
|
||||||
.flatten()
|
|
||||||
{
|
|
||||||
session_cookie
|
|
||||||
} else {
|
|
||||||
let user_session = UserSession::new();
|
|
||||||
let mut session = Session::new();
|
|
||||||
session.insert(SESSION_KEY, user_session.clone()).unwrap();
|
|
||||||
let cookie = store.store_session(session).await.unwrap().unwrap();
|
|
||||||
|
|
||||||
return Ok(Self::Created {
|
|
||||||
header: Cookie::new(SESSION_COOKIE_NAME, cookie)
|
|
||||||
.to_string()
|
|
||||||
.parse()
|
|
||||||
.unwrap(),
|
|
||||||
nonce: user_session.nonce,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
let session = match store.load_session(session_cookie.value().to_string()).await {
|
|
||||||
Ok(Some(s)) => s,
|
|
||||||
_ => {
|
|
||||||
debug!("Could not load session");
|
|
||||||
let mut cookie = session_cookie.clone();
|
|
||||||
cookie.make_removal();
|
|
||||||
return Ok(Self::Invalid(cookie.to_string().parse().unwrap()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let user_session = if let Some(user_session) = session.get::<UserSession>(SESSION_KEY) {
|
|
||||||
user_session
|
|
||||||
} else {
|
|
||||||
debug!("No `user_session` found in session");
|
|
||||||
let mut cookie = session_cookie.clone();
|
|
||||||
cookie.make_removal();
|
|
||||||
return Ok(Self::Invalid(cookie.to_string().parse().unwrap()));
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Self::Found(user_session.nonce))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
struct UserSession {
|
|
||||||
id: Uuid,
|
|
||||||
nonce: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UserSession {
|
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
id: Uuid::new_v4(),
|
|
||||||
nonce: rand::thread_rng()
|
|
||||||
.sample_iter(&Alphanumeric)
|
|
||||||
.take(16)
|
|
||||||
.map(char::from)
|
|
||||||
.collect(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,7 +4,6 @@ use headers::{
|
|||||||
authorization::{Basic, Bearer, Credentials},
|
authorization::{Basic, Bearer, Credentials},
|
||||||
Authorization, ContentType, Header, HeaderValue,
|
Authorization, ContentType, Header, HeaderValue,
|
||||||
};
|
};
|
||||||
use rand::{distributions::Alphanumeric, Rng};
|
|
||||||
use rsa::{pkcs1::FromRsaPrivateKey, RsaPrivateKey};
|
use rsa::{pkcs1::FromRsaPrivateKey, RsaPrivateKey};
|
||||||
use worker::*;
|
use worker::*;
|
||||||
|
|
||||||
@ -197,7 +196,6 @@ pub async fn main(req: Request, env: Env) -> Result<Response> {
|
|||||||
}
|
}
|
||||||
.and_then(|r| r.with_cors(&get_cors()))
|
.and_then(|r| r.with_cors(&get_cors()))
|
||||||
})
|
})
|
||||||
// TODO add browser session
|
|
||||||
.get_async(oidc::AUTHORIZE_PATH, |req, ctx| async move {
|
.get_async(oidc::AUTHORIZE_PATH, |req, ctx| async move {
|
||||||
let base_url: Url = ctx.var(BASE_URL_KEY)?.to_string().parse().unwrap();
|
let base_url: Url = ctx.var(BASE_URL_KEY)?.to_string().parse().unwrap();
|
||||||
let url = req.url()?;
|
let url = req.url()?;
|
||||||
@ -206,15 +204,18 @@ pub async fn main(req: Request, env: Env) -> Result<Response> {
|
|||||||
Ok(p) => p,
|
Ok(p) => p,
|
||||||
Err(_) => return CustomError::BadRequest("Bad query params".to_string()).into(),
|
Err(_) => return CustomError::BadRequest("Bad query params".to_string()).into(),
|
||||||
};
|
};
|
||||||
let nonce = rand::thread_rng()
|
|
||||||
.sample_iter(&Alphanumeric)
|
|
||||||
.take(16)
|
|
||||||
.map(char::from)
|
|
||||||
.collect();
|
|
||||||
let url = req.url()?;
|
let url = req.url()?;
|
||||||
let db_client = CFClient { ctx, url };
|
let db_client = CFClient { ctx, url };
|
||||||
match oidc::authorize(params, nonce, &db_client).await {
|
match oidc::authorize(params, &db_client).await {
|
||||||
Ok(url) => Response::redirect(base_url.join(&url).unwrap()),
|
Ok((url, session_cookie)) => {
|
||||||
|
Response::redirect(base_url.join(&url).unwrap()).map(|r| {
|
||||||
|
let mut headers = r.headers().clone();
|
||||||
|
headers
|
||||||
|
.set("set-cookie", &session_cookie.to_string())
|
||||||
|
.unwrap();
|
||||||
|
r.with_headers(headers)
|
||||||
|
})
|
||||||
|
}
|
||||||
Err(e) => match e {
|
Err(e) => match e {
|
||||||
CustomError::Redirect(url) => {
|
CustomError::Redirect(url) => {
|
||||||
CustomError::Redirect(base_url.join(&url).unwrap().to_string())
|
CustomError::Redirect(base_url.join(&url).unwrap().to_string())
|
||||||
@ -320,7 +321,7 @@ pub async fn main(req: Request, env: Env) -> Result<Response> {
|
|||||||
}
|
}
|
||||||
let url = req.url()?;
|
let url = req.url()?;
|
||||||
let db_client = CFClient { ctx, url };
|
let db_client = CFClient { ctx, url };
|
||||||
match oidc::sign_in(params, None, cookies.unwrap(), &db_client).await {
|
match oidc::sign_in(params, cookies.unwrap(), &db_client).await {
|
||||||
Ok(url) => Response::redirect(url),
|
Ok(url) => Response::redirect(url),
|
||||||
Err(e) => e.into(),
|
Err(e) => e.into(),
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user