Start on OIDC integration
This is absurdly insecure and jank to start but I just want a POC before I polish it
This commit is contained in:
parent
db70e8c52a
commit
657e5e6088
8 changed files with 638 additions and 5 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -4,3 +4,5 @@
|
|||
.idea/
|
||||
.vscode/
|
||||
result
|
||||
/config
|
||||
/database
|
381
Cargo.lock
generated
381
Cargo.lock
generated
|
@ -55,6 +55,21 @@ version = "0.2.16"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.4"
|
||||
|
@ -164,7 +179,7 @@ dependencies = [
|
|||
"fuzzy-matcher",
|
||||
"indicatif",
|
||||
"interim",
|
||||
"itertools",
|
||||
"itertools 0.11.0",
|
||||
"log",
|
||||
"ratatui",
|
||||
"rpassword",
|
||||
|
@ -199,7 +214,7 @@ dependencies = [
|
|||
"generic-array",
|
||||
"hex",
|
||||
"interim",
|
||||
"itertools",
|
||||
"itertools 0.11.0",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"memchr",
|
||||
|
@ -256,6 +271,7 @@ dependencies = [
|
|||
"eyre",
|
||||
"fs-err",
|
||||
"http",
|
||||
"openidconnect",
|
||||
"rand 0.8.5",
|
||||
"reqwest",
|
||||
"semver",
|
||||
|
@ -367,6 +383,12 @@ dependencies = [
|
|||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base16ct"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.1"
|
||||
|
@ -517,6 +539,21 @@ dependencies = [
|
|||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.3.0"
|
||||
|
@ -746,6 +783,18 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28f85c3514d2a6e64160359b45a3918c3b4178bcbf4ae5d03ab2d02e521c479a"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
|
@ -823,6 +872,41 @@ dependencies = [
|
|||
"syn 2.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.8"
|
||||
|
@ -934,6 +1018,26 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
||||
|
||||
[[package]]
|
||||
name = "dyn-clone"
|
||||
version = "1.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d"
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.16.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4"
|
||||
dependencies = [
|
||||
"der",
|
||||
"digest 0.10.7",
|
||||
"elliptic-curve",
|
||||
"rfc6979",
|
||||
"signature 2.1.0",
|
||||
"spki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ed25519"
|
||||
version = "1.5.3"
|
||||
|
@ -989,6 +1093,27 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
version = "0.13.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d97ca172ae9dc9f9b779a6e3a65d308f2af74e5b8c921299075bdb4a0370e914"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"crypto-bigint",
|
||||
"digest 0.10.7",
|
||||
"ff",
|
||||
"generic-array",
|
||||
"group",
|
||||
"hkdf",
|
||||
"pem-rfc7468",
|
||||
"pkcs8",
|
||||
"rand_core 0.6.4",
|
||||
"sec1",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.6"
|
||||
|
@ -1076,6 +1201,16 @@ version = "2.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
|
||||
|
||||
[[package]]
|
||||
name = "ff"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
|
||||
dependencies = [
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fiat-crypto"
|
||||
version = "0.2.1"
|
||||
|
@ -1286,8 +1421,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1296,6 +1433,17 @@ version = "0.28.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
|
||||
|
||||
[[package]]
|
||||
name = "group"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
|
||||
dependencies = [
|
||||
"ff",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.21"
|
||||
|
@ -1472,6 +1620,35 @@ dependencies = [
|
|||
"tokio-rustls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.4.0"
|
||||
|
@ -1496,6 +1673,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
|||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown 0.12.3",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1506,6 +1684,7 @@ checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
|
|||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.2",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1581,6 +1760,15 @@ dependencies = [
|
|||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.11.0"
|
||||
|
@ -1940,6 +2128,26 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||
|
||||
[[package]]
|
||||
name = "oauth2"
|
||||
version = "4.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c38841cdd844847e3e7c8d29cef9dcfed8877f8f56f9071f77843ecf3baf937f"
|
||||
dependencies = [
|
||||
"base64 0.13.1",
|
||||
"chrono",
|
||||
"getrandom 0.2.10",
|
||||
"http",
|
||||
"rand 0.8.5",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
"sha2 0.10.8",
|
||||
"thiserror",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
|
@ -1990,6 +2198,38 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "openidconnect"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62d6050f6a84b81f23c569f5607ad883293e57491036e318fafe6fc4895fadb1"
|
||||
dependencies = [
|
||||
"base64 0.13.1",
|
||||
"chrono",
|
||||
"dyn-clone",
|
||||
"ed25519-dalek 2.0.0",
|
||||
"hmac",
|
||||
"http",
|
||||
"itertools 0.10.5",
|
||||
"log",
|
||||
"oauth2",
|
||||
"p256",
|
||||
"p384",
|
||||
"rand 0.8.5",
|
||||
"rsa",
|
||||
"serde",
|
||||
"serde-value",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
"serde_plain",
|
||||
"serde_with",
|
||||
"sha2 0.10.8",
|
||||
"subtle",
|
||||
"thiserror",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.1.5"
|
||||
|
@ -2002,6 +2242,15 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "ordered-float"
|
||||
version = "2.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_pipe"
|
||||
version = "1.1.4"
|
||||
|
@ -2018,6 +2267,30 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "p256"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
|
||||
dependencies = [
|
||||
"ecdsa",
|
||||
"elliptic-curve",
|
||||
"primeorder",
|
||||
"sha2 0.10.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "p384"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209"
|
||||
dependencies = [
|
||||
"ecdsa",
|
||||
"elliptic-curve",
|
||||
"primeorder",
|
||||
"sha2 0.10.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
|
@ -2207,6 +2480,15 @@ dependencies = [
|
|||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "primeorder"
|
||||
version = "0.13.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7dbe9ed3b56368bd99483eb32fe9c17fdd3730aebadc906918ce78d54c7eeb4"
|
||||
dependencies = [
|
||||
"elliptic-curve",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.69"
|
||||
|
@ -2306,7 +2588,7 @@ dependencies = [
|
|||
"cassowary",
|
||||
"crossterm",
|
||||
"indoc",
|
||||
"itertools",
|
||||
"itertools 0.11.0",
|
||||
"lru",
|
||||
"paste",
|
||||
"strum",
|
||||
|
@ -2433,9 +2715,20 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"webpki-roots 0.25.2",
|
||||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rfc6979"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
|
||||
dependencies = [
|
||||
"hmac",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.16.20"
|
||||
|
@ -2692,6 +2985,20 @@ dependencies = [
|
|||
"untrusted 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sec1"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"der",
|
||||
"generic-array",
|
||||
"pkcs8",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.9.2"
|
||||
|
@ -2730,6 +3037,16 @@ dependencies = [
|
|||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-value"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
|
||||
dependencies = [
|
||||
"ordered-float",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.171"
|
||||
|
@ -2762,6 +3079,15 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_plain"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce1fc6db65a611022b23a0dec6975d63fb80a302cb3388835ff02c097258d50"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_regex"
|
||||
version = "1.1.0"
|
||||
|
@ -2784,6 +3110,35 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23"
|
||||
dependencies = [
|
||||
"base64 0.21.5",
|
||||
"chrono",
|
||||
"hex",
|
||||
"indexmap 1.9.3",
|
||||
"indexmap 2.0.2",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with_macros",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.6"
|
||||
|
@ -2959,7 +3314,7 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b7b278788e7be4d0d29c0f39497a0eef3fba6bbc8e70d8bf7fde46edeaa9e85"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"itertools 0.11.0",
|
||||
"nom",
|
||||
"unicode_categories",
|
||||
]
|
||||
|
@ -3019,7 +3374,7 @@ dependencies = [
|
|||
"tracing",
|
||||
"url",
|
||||
"uuid",
|
||||
"webpki-roots",
|
||||
"webpki-roots 0.24.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3695,6 +4050,7 @@ dependencies = [
|
|||
"form_urlencoded",
|
||||
"idna",
|
||||
"percent-encoding",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3902,6 +4258,12 @@ dependencies = [
|
|||
"rustls-webpki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.25.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
|
||||
|
||||
[[package]]
|
||||
name = "whoami"
|
||||
version = "1.4.1"
|
||||
|
@ -3952,6 +4314,15 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.51.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
|
|
|
@ -33,3 +33,4 @@ tower-http = { version = "0.4", features = ["trace"] }
|
|||
reqwest = { workspace = true }
|
||||
argon2 = "0.5.0"
|
||||
semver = { workspace = true }
|
||||
openidconnect = "3.4.0"
|
||||
|
|
|
@ -8,6 +8,7 @@ pub mod history;
|
|||
pub mod record;
|
||||
pub mod status;
|
||||
pub mod user;
|
||||
pub mod oidc;
|
||||
|
||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
|
|
214
atuin-server/src/handlers/oidc.rs
Normal file
214
atuin-server/src/handlers/oidc.rs
Normal file
|
@ -0,0 +1,214 @@
|
|||
use axum::{
|
||||
extract::{State, Query},
|
||||
response::Redirect,
|
||||
Json,
|
||||
};
|
||||
use http::StatusCode;
|
||||
use openidconnect::{
|
||||
core::{CoreAuthenticationFlow, CoreClient, CoreProviderMetadata},
|
||||
reqwest::async_http_client,
|
||||
AuthorizationCode, ClientId, ClientSecret, CsrfToken, IssuerUrl, Nonce, RedirectUrl, Scope,
|
||||
TokenResponse,
|
||||
};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use tracing::error;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::{ErrorResponse, ErrorResponseStatus, RespExt};
|
||||
use crate::router::AppState;
|
||||
use atuin_server_database::{Database, DbError, models::{NewUser, NewSession}};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct OIDCGetResponse {
|
||||
pub login_url: String
|
||||
}
|
||||
|
||||
pub async fn get<DB: Database>(state: State<AppState<DB>>) -> Result<Json<OIDCGetResponse>, ErrorResponseStatus<'static>> {
|
||||
if state.settings.oidc_authority.is_none()
|
||||
|| state.settings.oidc_client_id.is_none()
|
||||
|| state.settings.oidc_client_secret.is_none()
|
||||
{
|
||||
return Err(ErrorResponse::reply("OIDC not supported on this server").with_status(StatusCode::BAD_REQUEST));
|
||||
}
|
||||
|
||||
let url = state
|
||||
.settings
|
||||
.public_url
|
||||
.strip_suffix("/")
|
||||
.unwrap_or(&state.settings.public_url)
|
||||
.to_string()
|
||||
+ "/oidc/login";
|
||||
|
||||
Ok(Json(OIDCGetResponse {
|
||||
// This is dynamic to allow for backwards compatibility later
|
||||
// it also is relative to the client's configured server URL
|
||||
login_url: url,
|
||||
}))
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct LoginQuery {
|
||||
pub callback: String,
|
||||
}
|
||||
|
||||
pub async fn login<DB: Database>(
|
||||
state: State<AppState<DB>>,
|
||||
params: Query<LoginQuery>,
|
||||
) -> Result<Redirect, ErrorResponseStatus<'static>> {
|
||||
if state.settings.oidc_authority.is_none()
|
||||
|| state.settings.oidc_client_id.is_none()
|
||||
|| state.settings.oidc_client_secret.is_none()
|
||||
{
|
||||
return Err(ErrorResponse::reply("OIDC not supported on this server").with_status(StatusCode::BAD_REQUEST));
|
||||
}
|
||||
|
||||
let provider_metadata = CoreProviderMetadata::discover_async(
|
||||
IssuerUrl::new(state.settings.oidc_authority.clone().unwrap()).or(Err(ErrorResponse::reply("unable to parse configured oidc authority").with_status(StatusCode::INTERNAL_SERVER_ERROR)))?,
|
||||
async_http_client,
|
||||
)
|
||||
.await
|
||||
.or(Err(ErrorResponse::reply("unable to fetch oidc provider metadata").with_status(StatusCode::INTERNAL_SERVER_ERROR)))?;
|
||||
|
||||
let client = CoreClient::from_provider_metadata(
|
||||
provider_metadata,
|
||||
ClientId::new(state.settings.oidc_client_id.clone().unwrap()),
|
||||
Some(ClientSecret::new(
|
||||
state.settings.oidc_client_secret.clone().unwrap(),
|
||||
)),
|
||||
)
|
||||
// Set the URL the user will be redirected to after the authorization process.
|
||||
.set_redirect_uri(
|
||||
RedirectUrl::new(
|
||||
state
|
||||
.settings
|
||||
.public_url
|
||||
.strip_suffix("/")
|
||||
.unwrap_or(&state.settings.public_url)
|
||||
.to_string()
|
||||
+ "/oidc/callback",
|
||||
)
|
||||
.or(Err(ErrorResponse::reply("unable to parse constructed redirect uri").with_status(StatusCode::INTERNAL_SERVER_ERROR)))?,
|
||||
);
|
||||
|
||||
let url = client
|
||||
.authorize_url(
|
||||
CoreAuthenticationFlow::AuthorizationCode,
|
||||
|| CsrfToken::new(params.0.callback),
|
||||
Nonce::new_random,
|
||||
)
|
||||
.add_scopes(vec![Scope::new("profile".to_string()), Scope::new("email".to_string())])
|
||||
.url();
|
||||
|
||||
Ok(Redirect::to(url.0.as_str()))
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CallbackQuery {
|
||||
pub code: String,
|
||||
pub state: String
|
||||
}
|
||||
|
||||
pub async fn callback<DB: Database>(
|
||||
state: State<AppState<DB>>,
|
||||
params: Query<CallbackQuery>,
|
||||
) -> Result<Json<String>, ErrorResponseStatus<'static>> {
|
||||
if state.settings.oidc_authority.is_none()
|
||||
|| state.settings.oidc_client_id.is_none()
|
||||
|| state.settings.oidc_client_secret.is_none()
|
||||
{
|
||||
return Err(ErrorResponse::reply("OIDC not supported on this server").with_status(StatusCode::BAD_REQUEST));
|
||||
}
|
||||
|
||||
let provider_metadata = CoreProviderMetadata::discover_async(
|
||||
IssuerUrl::new(state.settings.oidc_authority.clone().unwrap()).or(Err(ErrorResponse::reply("unable to parse configured oidc authority").with_status(StatusCode::INTERNAL_SERVER_ERROR)))?,
|
||||
async_http_client,
|
||||
)
|
||||
.await
|
||||
.or(Err(ErrorResponse::reply("unable to fetch oidc provider metadata").with_status(StatusCode::INTERNAL_SERVER_ERROR)))?;
|
||||
|
||||
let client = CoreClient::from_provider_metadata(
|
||||
provider_metadata,
|
||||
ClientId::new(state.settings.oidc_client_id.clone().unwrap()),
|
||||
Some(ClientSecret::new(
|
||||
state.settings.oidc_client_secret.clone().unwrap(),
|
||||
)),
|
||||
).set_redirect_uri(
|
||||
RedirectUrl::new(
|
||||
state
|
||||
.settings
|
||||
.public_url
|
||||
.strip_suffix("/")
|
||||
.unwrap_or(&state.settings.public_url)
|
||||
.to_string()
|
||||
+ "/oidc/callback",
|
||||
)
|
||||
.or(Err(ErrorResponse::reply("unable to parse constructed redirect uri").with_status(StatusCode::INTERNAL_SERVER_ERROR)))?,
|
||||
);
|
||||
|
||||
let token_response = client
|
||||
.exchange_code(AuthorizationCode::new(params.0.code))
|
||||
.request_async(async_http_client)
|
||||
.await
|
||||
.or(Err(ErrorResponse::reply("unable to exchange oidc code for token").with_status(StatusCode::INTERNAL_SERVER_ERROR)))?;
|
||||
|
||||
let id_token = token_response.id_token().unwrap();
|
||||
// TODO actual audience validation
|
||||
let claims = dbg!(id_token
|
||||
.claims(&client.id_token_verifier().require_audience_match(false), |_: Option<&Nonce>| Ok(())))
|
||||
.or(Err(ErrorResponse::reply("unable to validate oidc token").with_status(StatusCode::INTERNAL_SERVER_ERROR)))?;
|
||||
|
||||
let db = &state.0.database;
|
||||
let username = claims.preferred_username().ok_or(ErrorResponse::reply("oidc token did not contain preferred_username").with_status(StatusCode::INTERNAL_SERVER_ERROR))?;
|
||||
let email = claims.email().ok_or(ErrorResponse::reply("oidc token did not contain email").with_status(StatusCode::INTERNAL_SERVER_ERROR))?;
|
||||
// Fetches the existing user ID, or registers them on the spot.
|
||||
let user_id = match db.get_user(username).await {
|
||||
Ok(u) => u.id,
|
||||
Err(DbError::NotFound) => {
|
||||
let new_user = NewUser {
|
||||
email: email.to_string(),
|
||||
username: username.to_string(),
|
||||
password: "".to_string(),
|
||||
};
|
||||
|
||||
match db.add_user(&new_user).await {
|
||||
Ok(id) => id,
|
||||
Err(e) => {
|
||||
error!("failed to add user via oidc: {}", e);
|
||||
return Err(
|
||||
ErrorResponse::reply("failed to add user via oidc").with_status(StatusCode::BAD_REQUEST)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(DbError::Other(e)) => {
|
||||
error!("failed to get user {}: {}", username.as_str(), e);
|
||||
|
||||
return Err(ErrorResponse::reply("database error")
|
||||
.with_status(StatusCode::INTERNAL_SERVER_ERROR));
|
||||
}
|
||||
};
|
||||
|
||||
// Creates a new session for the user
|
||||
let token = Uuid::new_v4().as_simple().to_string();
|
||||
let new_session = NewSession {
|
||||
user_id,
|
||||
token: (&token).into(),
|
||||
};
|
||||
|
||||
match db.add_session(&new_session).await {
|
||||
Ok(_) => (),
|
||||
Err(e) => {
|
||||
error!("failed to add session from oidc: {}", e);
|
||||
return Err(ErrorResponse::reply("failed to register user via oidc")
|
||||
.with_status(StatusCode::BAD_REQUEST))
|
||||
}
|
||||
};
|
||||
|
||||
dbg!(claims);
|
||||
dbg!(username);
|
||||
dbg!(email);
|
||||
|
||||
// TODO - redirect to localhost + client side aspect + clean stuff up
|
||||
|
||||
Ok(Json("it works probably wtf".to_string()))
|
||||
}
|
|
@ -111,6 +111,9 @@ pub fn router<DB: Database>(database: DB, settings: Settings<DB::Settings>) -> R
|
|||
.route("/user/:username", get(handlers::user::get))
|
||||
.route("/account", delete(handlers::user::delete))
|
||||
.route("/register", post(handlers::user::register))
|
||||
.route("/oidc", get(handlers::oidc::get))
|
||||
.route("/oidc/login", get(handlers::oidc::login))
|
||||
.route("/oidc/callback", get(handlers::oidc::callback))
|
||||
.route("/login", post(handlers::user::login));
|
||||
|
||||
let path = settings.path.as_str();
|
||||
|
|
|
@ -18,6 +18,10 @@ pub struct Settings<DbSettings> {
|
|||
pub page_size: i64,
|
||||
pub register_webhook_url: Option<String>,
|
||||
pub register_webhook_username: String,
|
||||
pub public_url: String,
|
||||
pub oidc_authority: Option<String>,
|
||||
pub oidc_client_id: Option<String>,
|
||||
pub oidc_client_secret: Option<String>,
|
||||
|
||||
#[serde(flatten)]
|
||||
pub db_settings: DbSettings,
|
||||
|
|
37
docker-compose.dev.yml
Normal file
37
docker-compose.dev.yml
Normal file
|
@ -0,0 +1,37 @@
|
|||
version: '3.5'
|
||||
services:
|
||||
atuin:
|
||||
restart: always
|
||||
image: atuinlocal:latest
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
network: host
|
||||
command: server start
|
||||
volumes:
|
||||
- "./config:/config"
|
||||
links:
|
||||
- postgresql:db
|
||||
ports:
|
||||
- 8888:8888
|
||||
environment:
|
||||
ATUIN_HOST: "0.0.0.0"
|
||||
ATUIN_OPEN_REGISTRATION: "true"
|
||||
ATUIN_DB_URI: postgres://atuin:really-insecure@db/atuin
|
||||
postgresql:
|
||||
image: postgres:14
|
||||
restart: unless-stopped
|
||||
volumes: # Don't remove permanent storage for index database files!
|
||||
- "./database:/var/lib/postgresql/data/"
|
||||
environment:
|
||||
POSTGRES_USER: atuin
|
||||
POSTGRES_PASSWORD: really-insecure
|
||||
POSTGRES_DB: atuin
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: atuinnet
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: 172.20.0.0/16
|
Loading…
Reference in a new issue