Redirect user for authentication
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			This commit is contained in:
		
							
								
								
									
										580
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										580
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -189,6 +189,41 @@ version = "1.0.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" | ||||
|  | ||||
| [[package]] | ||||
| name = "aead" | ||||
| version = "0.5.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" | ||||
| dependencies = [ | ||||
|  "crypto-common", | ||||
|  "generic-array", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "aes" | ||||
| version = "0.8.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "cipher", | ||||
|  "cpufeatures", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "aes-gcm" | ||||
| version = "0.10.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "82e1366e0c69c9f927b1fa5ce2c7bf9eafc8f9268c0b9800729e8b267612447c" | ||||
| dependencies = [ | ||||
|  "aead", | ||||
|  "aes", | ||||
|  "cipher", | ||||
|  "ctr", | ||||
|  "ghash", | ||||
|  "subtle", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "ahash" | ||||
| version = "0.7.6" | ||||
| @@ -341,6 +376,25 @@ dependencies = [ | ||||
|  "serde", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "bincode" | ||||
| version = "2.0.0-rc.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f11ea1a0346b94ef188834a65c068a03aec181c94896d481d7a0a40d85b0ce95" | ||||
| dependencies = [ | ||||
|  "bincode_derive", | ||||
|  "serde", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "bincode_derive" | ||||
| version = "2.0.0-rc.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7e30759b3b99a1b802a7a3aa21c85c3ded5c28e1c83170d82d70f08bbf7f3e4c" | ||||
| dependencies = [ | ||||
|  "virtue", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "bitflags" | ||||
| version = "1.3.2" | ||||
| @@ -377,6 +431,12 @@ dependencies = [ | ||||
|  "alloc-stdlib", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "bumpalo" | ||||
| version = "3.12.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" | ||||
|  | ||||
| [[package]] | ||||
| name = "bytes" | ||||
| version = "1.4.0" | ||||
| @@ -407,6 +467,16 @@ version = "1.0.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | ||||
|  | ||||
| [[package]] | ||||
| name = "cipher" | ||||
| version = "0.4.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" | ||||
| dependencies = [ | ||||
|  "crypto-common", | ||||
|  "inout", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "clap" | ||||
| version = "4.2.4" | ||||
| @@ -472,6 +542,22 @@ dependencies = [ | ||||
|  "version_check", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "core-foundation" | ||||
| version = "0.9.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" | ||||
| dependencies = [ | ||||
|  "core-foundation-sys", | ||||
|  "libc", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "core-foundation-sys" | ||||
| version = "0.8.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" | ||||
|  | ||||
| [[package]] | ||||
| name = "cpufeatures" | ||||
| version = "0.2.7" | ||||
| @@ -497,9 +583,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" | ||||
| dependencies = [ | ||||
|  "generic-array", | ||||
|  "rand_core", | ||||
|  "typenum", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "ctr" | ||||
| version = "0.9.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" | ||||
| dependencies = [ | ||||
|  "cipher", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "derive_more" | ||||
| version = "0.99.17" | ||||
| @@ -566,6 +662,15 @@ dependencies = [ | ||||
|  "libc", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "fastrand" | ||||
| version = "1.9.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" | ||||
| dependencies = [ | ||||
|  "instant", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "flate2" | ||||
| version = "1.0.25" | ||||
| @@ -582,6 +687,21 @@ version = "1.0.7" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" | ||||
|  | ||||
| [[package]] | ||||
| name = "foreign-types" | ||||
| version = "0.3.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" | ||||
| dependencies = [ | ||||
|  "foreign-types-shared", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "foreign-types-shared" | ||||
| version = "0.1.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" | ||||
|  | ||||
| [[package]] | ||||
| name = "form_urlencoded" | ||||
| version = "1.1.0" | ||||
| @@ -591,12 +711,32 @@ dependencies = [ | ||||
|  "percent-encoding", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "futures-channel" | ||||
| version = "0.3.28" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" | ||||
| dependencies = [ | ||||
|  "futures-core", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "futures-core" | ||||
| version = "0.3.28" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" | ||||
|  | ||||
| [[package]] | ||||
| name = "futures-macro" | ||||
| version = "0.3.28" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.15", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "futures-sink" | ||||
| version = "0.3.28" | ||||
| @@ -616,9 +756,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" | ||||
| dependencies = [ | ||||
|  "futures-core", | ||||
|  "futures-macro", | ||||
|  "futures-task", | ||||
|  "pin-project-lite", | ||||
|  "pin-utils", | ||||
|  "slab", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -642,6 +784,16 @@ dependencies = [ | ||||
|  "wasi", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "ghash" | ||||
| version = "0.5.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" | ||||
| dependencies = [ | ||||
|  "opaque-debug", | ||||
|  "polyval", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "h2" | ||||
| version = "0.3.18" | ||||
| @@ -699,6 +851,17 @@ dependencies = [ | ||||
|  "itoa", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "http-body" | ||||
| version = "0.4.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" | ||||
| dependencies = [ | ||||
|  "bytes", | ||||
|  "http", | ||||
|  "pin-project-lite", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "httparse" | ||||
| version = "1.8.0" | ||||
| @@ -726,6 +889,43 @@ version = "2.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" | ||||
|  | ||||
| [[package]] | ||||
| name = "hyper" | ||||
| version = "0.14.26" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" | ||||
| dependencies = [ | ||||
|  "bytes", | ||||
|  "futures-channel", | ||||
|  "futures-core", | ||||
|  "futures-util", | ||||
|  "h2", | ||||
|  "http", | ||||
|  "http-body", | ||||
|  "httparse", | ||||
|  "httpdate", | ||||
|  "itoa", | ||||
|  "pin-project-lite", | ||||
|  "socket2", | ||||
|  "tokio", | ||||
|  "tower-service", | ||||
|  "tracing", | ||||
|  "want", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "hyper-tls" | ||||
| version = "0.5.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" | ||||
| dependencies = [ | ||||
|  "bytes", | ||||
|  "hyper", | ||||
|  "native-tls", | ||||
|  "tokio", | ||||
|  "tokio-native-tls", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "idna" | ||||
| version = "0.3.0" | ||||
| @@ -746,6 +946,24 @@ dependencies = [ | ||||
|  "hashbrown", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "inout" | ||||
| version = "0.1.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" | ||||
| dependencies = [ | ||||
|  "generic-array", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "instant" | ||||
| version = "0.1.12" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "io-lifetimes" | ||||
| version = "1.0.10" | ||||
| @@ -757,6 +975,12 @@ dependencies = [ | ||||
|  "windows-sys 0.48.0", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "ipnet" | ||||
| version = "2.7.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" | ||||
|  | ||||
| [[package]] | ||||
| name = "is-terminal" | ||||
| version = "0.4.7" | ||||
| @@ -784,6 +1008,15 @@ dependencies = [ | ||||
|  "libc", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "js-sys" | ||||
| version = "0.3.61" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" | ||||
| dependencies = [ | ||||
|  "wasm-bindgen", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "language-tags" | ||||
| version = "0.3.2" | ||||
| @@ -900,6 +1133,24 @@ dependencies = [ | ||||
|  "windows-sys 0.45.0", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "native-tls" | ||||
| version = "0.2.11" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" | ||||
| dependencies = [ | ||||
|  "lazy_static", | ||||
|  "libc", | ||||
|  "log", | ||||
|  "openssl", | ||||
|  "openssl-probe", | ||||
|  "openssl-sys", | ||||
|  "schannel", | ||||
|  "security-framework", | ||||
|  "security-framework-sys", | ||||
|  "tempfile", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "nom" | ||||
| version = "7.1.3" | ||||
| @@ -934,11 +1185,19 @@ name = "oidc-test-client" | ||||
| version = "0.1.0" | ||||
| dependencies = [ | ||||
|  "actix-web", | ||||
|  "aes-gcm", | ||||
|  "askama", | ||||
|  "base64", | ||||
|  "bincode", | ||||
|  "clap", | ||||
|  "env_logger", | ||||
|  "futures-util", | ||||
|  "lazy_static", | ||||
|  "log", | ||||
|  "rand", | ||||
|  "reqwest", | ||||
|  "serde", | ||||
|  "urlencoding", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| @@ -947,6 +1206,56 @@ version = "1.17.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" | ||||
|  | ||||
| [[package]] | ||||
| name = "opaque-debug" | ||||
| version = "0.3.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" | ||||
|  | ||||
| [[package]] | ||||
| name = "openssl" | ||||
| version = "0.10.52" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "01b8574602df80f7b85fdfc5392fa884a4e3b3f4f35402c070ab34c3d3f78d56" | ||||
| dependencies = [ | ||||
|  "bitflags", | ||||
|  "cfg-if", | ||||
|  "foreign-types", | ||||
|  "libc", | ||||
|  "once_cell", | ||||
|  "openssl-macros", | ||||
|  "openssl-sys", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "openssl-macros" | ||||
| version = "0.1.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 2.0.15", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "openssl-probe" | ||||
| version = "0.1.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" | ||||
|  | ||||
| [[package]] | ||||
| name = "openssl-sys" | ||||
| version = "0.9.87" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e" | ||||
| dependencies = [ | ||||
|  "cc", | ||||
|  "libc", | ||||
|  "pkg-config", | ||||
|  "vcpkg", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "parking_lot" | ||||
| version = "0.12.1" | ||||
| @@ -965,7 +1274,7 @@ checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "libc", | ||||
|  "redox_syscall", | ||||
|  "redox_syscall 0.2.16", | ||||
|  "smallvec", | ||||
|  "windows-sys 0.45.0", | ||||
| ] | ||||
| @@ -1000,6 +1309,18 @@ version = "0.3.26" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" | ||||
|  | ||||
| [[package]] | ||||
| name = "polyval" | ||||
| version = "0.6.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7ef234e08c11dfcb2e56f79fd70f6f2eb7f025c0ce2333e82f4f0518ecad30c6" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "cpufeatures", | ||||
|  "opaque-debug", | ||||
|  "universal-hash", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "ppv-lite86" | ||||
| version = "0.2.17" | ||||
| @@ -1063,6 +1384,15 @@ dependencies = [ | ||||
|  "bitflags", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "redox_syscall" | ||||
| version = "0.3.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" | ||||
| dependencies = [ | ||||
|  "bitflags", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "regex" | ||||
| version = "1.8.1" | ||||
| @@ -1080,6 +1410,43 @@ version = "0.7.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" | ||||
|  | ||||
| [[package]] | ||||
| name = "reqwest" | ||||
| version = "0.11.16" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" | ||||
| dependencies = [ | ||||
|  "base64", | ||||
|  "bytes", | ||||
|  "encoding_rs", | ||||
|  "futures-core", | ||||
|  "futures-util", | ||||
|  "h2", | ||||
|  "http", | ||||
|  "http-body", | ||||
|  "hyper", | ||||
|  "hyper-tls", | ||||
|  "ipnet", | ||||
|  "js-sys", | ||||
|  "log", | ||||
|  "mime", | ||||
|  "native-tls", | ||||
|  "once_cell", | ||||
|  "percent-encoding", | ||||
|  "pin-project-lite", | ||||
|  "serde", | ||||
|  "serde_json", | ||||
|  "serde_urlencoded", | ||||
|  "tokio", | ||||
|  "tokio-native-tls", | ||||
|  "tower-service", | ||||
|  "url", | ||||
|  "wasm-bindgen", | ||||
|  "wasm-bindgen-futures", | ||||
|  "web-sys", | ||||
|  "winreg", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "rustc_version" | ||||
| version = "0.4.0" | ||||
| @@ -1109,12 +1476,44 @@ version = "1.0.13" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" | ||||
|  | ||||
| [[package]] | ||||
| name = "schannel" | ||||
| version = "0.1.21" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" | ||||
| dependencies = [ | ||||
|  "windows-sys 0.42.0", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "scopeguard" | ||||
| version = "1.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" | ||||
|  | ||||
| [[package]] | ||||
| name = "security-framework" | ||||
| version = "2.8.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" | ||||
| dependencies = [ | ||||
|  "bitflags", | ||||
|  "core-foundation", | ||||
|  "core-foundation-sys", | ||||
|  "libc", | ||||
|  "security-framework-sys", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "security-framework-sys" | ||||
| version = "2.8.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" | ||||
| dependencies = [ | ||||
|  "core-foundation-sys", | ||||
|  "libc", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "semver" | ||||
| version = "1.0.17" | ||||
| @@ -1215,6 +1614,12 @@ version = "0.10.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" | ||||
|  | ||||
| [[package]] | ||||
| name = "subtle" | ||||
| version = "2.4.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" | ||||
|  | ||||
| [[package]] | ||||
| name = "syn" | ||||
| version = "1.0.109" | ||||
| @@ -1237,6 +1642,19 @@ dependencies = [ | ||||
|  "unicode-ident", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "tempfile" | ||||
| version = "3.5.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "fastrand", | ||||
|  "redox_syscall 0.3.5", | ||||
|  "rustix", | ||||
|  "windows-sys 0.45.0", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "termcolor" | ||||
| version = "1.2.0" | ||||
| @@ -1305,6 +1723,16 @@ dependencies = [ | ||||
|  "windows-sys 0.48.0", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "tokio-native-tls" | ||||
| version = "0.3.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" | ||||
| dependencies = [ | ||||
|  "native-tls", | ||||
|  "tokio", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "tokio-util" | ||||
| version = "0.7.8" | ||||
| @@ -1319,6 +1747,12 @@ dependencies = [ | ||||
|  "tracing", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "tower-service" | ||||
| version = "0.3.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" | ||||
|  | ||||
| [[package]] | ||||
| name = "tracing" | ||||
| version = "0.1.38" | ||||
| @@ -1339,6 +1773,12 @@ dependencies = [ | ||||
|  "once_cell", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "try-lock" | ||||
| version = "0.2.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" | ||||
|  | ||||
| [[package]] | ||||
| name = "typenum" | ||||
| version = "1.16.0" | ||||
| @@ -1375,6 +1815,16 @@ dependencies = [ | ||||
|  "tinyvec", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "universal-hash" | ||||
| version = "0.5.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5" | ||||
| dependencies = [ | ||||
|  "crypto-common", | ||||
|  "subtle", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "url" | ||||
| version = "2.3.1" | ||||
| @@ -1386,24 +1836,128 @@ dependencies = [ | ||||
|  "percent-encoding", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "urlencoding" | ||||
| version = "2.1.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" | ||||
|  | ||||
| [[package]] | ||||
| name = "utf8parse" | ||||
| version = "0.2.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" | ||||
|  | ||||
| [[package]] | ||||
| name = "vcpkg" | ||||
| version = "0.2.15" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" | ||||
|  | ||||
| [[package]] | ||||
| name = "version_check" | ||||
| version = "0.9.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" | ||||
|  | ||||
| [[package]] | ||||
| name = "virtue" | ||||
| version = "0.0.13" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9dcc60c0624df774c82a0ef104151231d37da4962957d691c011c852b2473314" | ||||
|  | ||||
| [[package]] | ||||
| name = "want" | ||||
| version = "0.3.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" | ||||
| dependencies = [ | ||||
|  "log", | ||||
|  "try-lock", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "wasi" | ||||
| version = "0.11.0+wasi-snapshot-preview1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" | ||||
|  | ||||
| [[package]] | ||||
| name = "wasm-bindgen" | ||||
| version = "0.2.84" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "wasm-bindgen-macro", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "wasm-bindgen-backend" | ||||
| version = "0.2.84" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" | ||||
| dependencies = [ | ||||
|  "bumpalo", | ||||
|  "log", | ||||
|  "once_cell", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 1.0.109", | ||||
|  "wasm-bindgen-shared", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "wasm-bindgen-futures" | ||||
| version = "0.4.34" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "js-sys", | ||||
|  "wasm-bindgen", | ||||
|  "web-sys", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "wasm-bindgen-macro" | ||||
| version = "0.2.84" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" | ||||
| dependencies = [ | ||||
|  "quote", | ||||
|  "wasm-bindgen-macro-support", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "wasm-bindgen-macro-support" | ||||
| version = "0.2.84" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn 1.0.109", | ||||
|  "wasm-bindgen-backend", | ||||
|  "wasm-bindgen-shared", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "wasm-bindgen-shared" | ||||
| version = "0.2.84" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" | ||||
|  | ||||
| [[package]] | ||||
| name = "web-sys" | ||||
| version = "0.3.61" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" | ||||
| dependencies = [ | ||||
|  "js-sys", | ||||
|  "wasm-bindgen", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "winapi" | ||||
| version = "0.3.9" | ||||
| @@ -1435,6 +1989,21 @@ version = "0.4.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | ||||
|  | ||||
| [[package]] | ||||
| name = "windows-sys" | ||||
| version = "0.42.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" | ||||
| dependencies = [ | ||||
|  "windows_aarch64_gnullvm 0.42.2", | ||||
|  "windows_aarch64_msvc 0.42.2", | ||||
|  "windows_i686_gnu 0.42.2", | ||||
|  "windows_i686_msvc 0.42.2", | ||||
|  "windows_x86_64_gnu 0.42.2", | ||||
|  "windows_x86_64_gnullvm 0.42.2", | ||||
|  "windows_x86_64_msvc 0.42.2", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "windows-sys" | ||||
| version = "0.45.0" | ||||
| @@ -1567,6 +2136,15 @@ version = "0.48.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" | ||||
|  | ||||
| [[package]] | ||||
| name = "winreg" | ||||
| version = "0.10.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" | ||||
| dependencies = [ | ||||
|  "winapi", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "zstd" | ||||
| version = "0.12.3+zstd.1.5.2" | ||||
|   | ||||
							
								
								
									
										12
									
								
								Cargo.toml
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Cargo.toml
									
									
									
									
									
								
							| @@ -8,7 +8,15 @@ edition = "2021" | ||||
| [dependencies] | ||||
| log = "0.4.17" | ||||
| env_logger = "0.10.0" | ||||
| clap = {version="4.2.4", features=["derive", "env"]} | ||||
| clap = { version = "4.2.4", features = ["derive", "env"] } | ||||
| lazy_static = "1.4.0" | ||||
| actix-web = "4.3.1" | ||||
| askama = "0.12.0" | ||||
| askama = "0.12.0" | ||||
| serde = { version = "1.0.160", features = ["derive"] } | ||||
| reqwest = { version = "0.11.16", features = ["json"] } | ||||
| urlencoding = "2.1.2" | ||||
| futures-util = "0.3.28" | ||||
| aes-gcm = "0.10.1" | ||||
| base64 = "0.21.0" | ||||
| rand = "0.8.5" | ||||
| bincode = {version="2.0.0-rc.3",features=["serde"]} | ||||
							
								
								
									
										58
									
								
								src/app_config.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/app_config.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| use clap::Parser; | ||||
|  | ||||
| const REDIRECT_URI: &str = "/redirect"; | ||||
|  | ||||
| /// Basic OpenID test client | ||||
| #[derive(Parser, Debug)] | ||||
| pub struct AppConfig { | ||||
|     /// Listen URL | ||||
|     #[arg(short, long, env, default_value = "0.0.0.0:7510")] | ||||
|     pub listen_addr: String, | ||||
|  | ||||
|     /// Public URL, the URL where this service is accessible, without the trailing slash | ||||
|     #[arg(short, long, env, default_value = "http://localhost:7510")] | ||||
|     pub public_url: String, | ||||
|  | ||||
|     /// URL where the OpenID configuration can be found | ||||
|     #[arg(short, long, env)] | ||||
|     pub configuration_url: String, | ||||
|  | ||||
|     /// OpenID client ID | ||||
|     #[arg(long, env)] | ||||
|     pub client_id: String, | ||||
|  | ||||
|     /// OpenID client secret | ||||
|     #[arg(long, env)] | ||||
|     pub client_secret: String, | ||||
|  | ||||
|     /// Proxy IP, might end with a "*" | ||||
|     #[clap(long, env)] | ||||
|     pub proxy_ip: Option<String>, | ||||
| } | ||||
|  | ||||
| impl AppConfig { | ||||
|     pub fn get() -> &'static Self { | ||||
|         &CONF | ||||
|     } | ||||
|  | ||||
|     pub fn redirect_url(&self) -> String { | ||||
|         format!("{}{}", self.public_url, REDIRECT_URI) | ||||
|     } | ||||
| } | ||||
|  | ||||
| lazy_static::lazy_static! { | ||||
|     static ref CONF: AppConfig = { | ||||
|         AppConfig::parse() | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #[cfg(test)] | ||||
| mod test { | ||||
|     use crate::app_config::AppConfig; | ||||
|  | ||||
|     #[test] | ||||
|     fn verify_cli() { | ||||
|         use clap::CommandFactory; | ||||
|         AppConfig::command().debug_assert(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										97
									
								
								src/crypto_wrapper.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/crypto_wrapper.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| use std::io::ErrorKind; | ||||
|  | ||||
| use crate::Res; | ||||
| use aes_gcm::aead::{Aead, OsRng}; | ||||
| use aes_gcm::{Aes256Gcm, Key, KeyInit, Nonce}; | ||||
| use base64::engine::general_purpose::STANDARD as BASE64_STANDARD; | ||||
| use base64::Engine as _; | ||||
| use bincode::{Decode, Encode}; | ||||
| use rand::Rng; | ||||
|  | ||||
| const NONCE_LEN: usize = 12; | ||||
|  | ||||
| pub struct CryptoWrapper { | ||||
|     key: Key<Aes256Gcm>, | ||||
| } | ||||
|  | ||||
| impl CryptoWrapper { | ||||
|     /// Generate a new memory wrapper | ||||
|     pub fn new_random() -> Self { | ||||
|         Self { | ||||
|             key: Aes256Gcm::generate_key(&mut OsRng), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Encrypt some data | ||||
|     pub fn encrypt<T: Encode + Decode>(&self, data: &T) -> Res<String> { | ||||
|         let aes_key = Aes256Gcm::new(&self.key); | ||||
|         let nonce_bytes = rand::thread_rng().gen::<[u8; NONCE_LEN]>(); | ||||
|  | ||||
|         let serialized_data = bincode::encode_to_vec(data, bincode::config::standard())?; | ||||
|  | ||||
|         let mut enc = aes_key | ||||
|             .encrypt(Nonce::from_slice(&nonce_bytes), serialized_data.as_slice()) | ||||
|             .unwrap(); | ||||
|         enc.extend_from_slice(&nonce_bytes); | ||||
|  | ||||
|         Ok(BASE64_STANDARD.encode(enc)) | ||||
|     } | ||||
|  | ||||
|     /// Decrypt some data previously encrypted using the [`CryptoWrapper::encrypt`] method | ||||
|     pub fn decrypt<T: Decode>(&self, input: &str) -> Res<T> { | ||||
|         let bytes = BASE64_STANDARD.decode(input)?; | ||||
|  | ||||
|         if bytes.len() < NONCE_LEN { | ||||
|             return Err(Box::new(std::io::Error::new( | ||||
|                 ErrorKind::Other, | ||||
|                 "Input string is smaller than nonce!", | ||||
|             ))); | ||||
|         } | ||||
|  | ||||
|         let (enc, nonce) = bytes.split_at(bytes.len() - NONCE_LEN); | ||||
|         assert_eq!(nonce.len(), NONCE_LEN); | ||||
|  | ||||
|         let aes_key = Aes256Gcm::new(&self.key); | ||||
|  | ||||
|         let dec = match aes_key.decrypt(Nonce::from_slice(nonce), enc) { | ||||
|             Ok(d) => d, | ||||
|             Err(e) => { | ||||
|                 log::error!("Failed to decrypt wrapped data! {:#?}", e); | ||||
|                 return Err(Box::new(std::io::Error::new( | ||||
|                     ErrorKind::Other, | ||||
|                     "Failed to decrypt wrapped data!", | ||||
|                 ))); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         Ok(bincode::decode_from_slice(&dec, bincode::config::standard())?.0) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(test)] | ||||
| mod test { | ||||
|     use crate::crypto_wrapper::CryptoWrapper; | ||||
|     use bincode::{Decode, Encode}; | ||||
|  | ||||
|     #[derive(Encode, Decode, Eq, PartialEq, Debug)] | ||||
|     struct Message(String); | ||||
|  | ||||
|     #[test] | ||||
|     fn encrypt_and_decrypt() { | ||||
|         let wrapper = CryptoWrapper::new_random(); | ||||
|         let msg = Message("Pierre was here".to_string()); | ||||
|         let enc = wrapper.encrypt(&msg).unwrap(); | ||||
|         let dec: Message = wrapper.decrypt(&enc).unwrap(); | ||||
|  | ||||
|         assert_eq!(dec, msg) | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn encrypt_and_decrypt_invalid() { | ||||
|         let wrapper_1 = CryptoWrapper::new_random(); | ||||
|         let wrapper_2 = CryptoWrapper::new_random(); | ||||
|         let msg = Message("Pierre was here".to_string()); | ||||
|         let enc = wrapper_1.encrypt(&msg).unwrap(); | ||||
|         wrapper_2.decrypt::<Message>(&enc).unwrap_err(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										10
									
								
								src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/lib.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| use std::error::Error; | ||||
|  | ||||
| pub type Res<A = ()> = Result<A, Box<dyn Error>>; | ||||
|  | ||||
| pub mod app_config; | ||||
| pub mod crypto_wrapper; | ||||
| pub mod openid_primitives; | ||||
| pub mod remote_ip; | ||||
| pub mod state_manager; | ||||
| pub mod time_utils; | ||||
							
								
								
									
										92
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								src/main.rs
									
									
									
									
									
								
							| @@ -1,42 +1,10 @@ | ||||
| use actix_web::{get, App, HttpResponse, HttpServer}; | ||||
| use askama::Template; | ||||
| use clap::Parser; | ||||
|  | ||||
| /// Basic OpenID test client | ||||
| #[derive(Parser, Debug)] | ||||
| struct AppConfig { | ||||
|     /// Listen URL | ||||
|     #[arg(short, long, env, default_value = "0.0.0.0:7510")] | ||||
|     listen_addr: String, | ||||
|  | ||||
|     /// Public URL, the URL where this service is accessible, without the trailing slash | ||||
|     #[arg(short, long, env, default_value = "http://localhost:7510")] | ||||
|     public_url: String, | ||||
|  | ||||
|     /// URL where the OpenID configuration can be found | ||||
|     #[arg(short, long, env)] | ||||
|     configuration_url: String, | ||||
|  | ||||
|     /// OpenID client ID | ||||
|     #[arg(long, env)] | ||||
|     client_id: String, | ||||
|  | ||||
|     /// OpenID client secret | ||||
|     #[arg(long, env)] | ||||
|     client_secret: String, | ||||
| } | ||||
|  | ||||
| impl AppConfig { | ||||
|     pub fn redirect_url(&self) -> String { | ||||
|         format!("{}/redirect", self.public_url) | ||||
|     } | ||||
| } | ||||
|  | ||||
| lazy_static::lazy_static! { | ||||
|     static ref CONF: AppConfig = { | ||||
|         AppConfig::parse() | ||||
|     }; | ||||
| } | ||||
| use oidc_test_client::app_config::AppConfig; | ||||
| use oidc_test_client::openid_primitives::OpenIDConfig; | ||||
| use oidc_test_client::remote_ip::RemoteIP; | ||||
| use oidc_test_client::state_manager::StateManager; | ||||
|  | ||||
| #[get("/assets/bootstrap.min.css")] | ||||
| async fn bootstrap() -> HttpResponse { | ||||
| @@ -62,32 +30,48 @@ struct HomeTemplate { | ||||
| async fn home() -> HttpResponse { | ||||
|     HttpResponse::Ok().content_type("text/html").body( | ||||
|         HomeTemplate { | ||||
|             redirect_url: CONF.redirect_url(), | ||||
|             redirect_url: AppConfig::get().redirect_url(), | ||||
|         } | ||||
|         .render() | ||||
|         .unwrap(), | ||||
|     ) | ||||
| } | ||||
|  | ||||
| #[get("/start")] | ||||
| async fn start(remote_ip: RemoteIP) -> HttpResponse { | ||||
|     let config = OpenIDConfig::load_from(&AppConfig::get().configuration_url) | ||||
|         .await | ||||
|         .expect("Failed to load provider configuration!"); | ||||
|  | ||||
|     let authorization_url = config.authorization_url( | ||||
|         &AppConfig::get().client_id, | ||||
|         &StateManager::gen_state(&remote_ip).expect("Failed to generate state!"), | ||||
|         &AppConfig::get().redirect_url(), | ||||
|     ); | ||||
|  | ||||
|     HttpResponse::Found() | ||||
|         .append_header(("Location", authorization_url)) | ||||
|         .finish() | ||||
| } | ||||
|  | ||||
| #[actix_web::main] | ||||
| async fn main() -> std::io::Result<()> { | ||||
|     env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); | ||||
|     log::info!("Will listen on {}", CONF.listen_addr); | ||||
|  | ||||
|     HttpServer::new(|| App::new().service(bootstrap).service(cover).service(home)) | ||||
|         .bind(&CONF.listen_addr) | ||||
|         .expect("Failed to bind server!") | ||||
|         .run() | ||||
|         .await | ||||
| } | ||||
|  | ||||
| #[cfg(test)] | ||||
| mod test { | ||||
|     use crate::AppConfig; | ||||
|  | ||||
|     #[test] | ||||
|     fn verify_cli() { | ||||
|         use clap::CommandFactory; | ||||
|         AppConfig::command().debug_assert(); | ||||
|     } | ||||
|     log::info!("Init state manager"); | ||||
|     StateManager::init(); | ||||
|  | ||||
|     log::info!("Will listen on {}", AppConfig::get().listen_addr); | ||||
|  | ||||
|     HttpServer::new(|| { | ||||
|         App::new() | ||||
|             .service(bootstrap) | ||||
|             .service(cover) | ||||
|             .service(home) | ||||
|             .service(start) | ||||
|     }) | ||||
|     .bind(&AppConfig::get().listen_addr) | ||||
|     .expect("Failed to bind server!") | ||||
|     .run() | ||||
|     .await | ||||
| } | ||||
|   | ||||
							
								
								
									
										24
									
								
								src/openid_primitives.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/openid_primitives.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| use crate::Res; | ||||
|  | ||||
| #[derive(Debug, Clone, serde::Deserialize)] | ||||
| pub struct OpenIDConfig { | ||||
|     pub authorization_endpoint: String, | ||||
|     pub token_endpoint: String, | ||||
|     pub userinfo_endpoint: String, | ||||
| } | ||||
|  | ||||
| impl OpenIDConfig { | ||||
|     /// Load OpenID configuration from a given URL | ||||
|     pub async fn load_from(url: &str) -> Res<Self> { | ||||
|         Ok(reqwest::get(url).await?.json().await?) | ||||
|     } | ||||
|  | ||||
|     /// Get the authorization URL where a user should be redirect | ||||
|     pub fn authorization_url(&self, client_id: &str, state: &str, redirect_uri: &str) -> String { | ||||
|         let client_id = urlencoding::encode(client_id); | ||||
|         let state = urlencoding::encode(state); | ||||
|         let redirect_uri = urlencoding::encode(redirect_uri); | ||||
|  | ||||
|         format!("{}?response_type=code&scope=openid%20profile%20email&client_id={client_id}&state={state}&redirect_uri={redirect_uri}", self.authorization_endpoint) | ||||
|     } | ||||
| } | ||||
							
								
								
									
										202
									
								
								src/remote_ip.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								src/remote_ip.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,202 @@ | ||||
| use std::net::{IpAddr, Ipv6Addr}; | ||||
|  | ||||
| use crate::app_config::AppConfig; | ||||
| use actix_web::dev::Payload; | ||||
| use actix_web::{Error, FromRequest, HttpRequest}; | ||||
| use futures_util::future::{ready, Ready}; | ||||
| use std::str::FromStr; | ||||
|  | ||||
| /// Parse an IP address | ||||
| pub fn parse_ip(ip: &str) -> Option<IpAddr> { | ||||
|     let mut ip = match IpAddr::from_str(ip) { | ||||
|         Ok(ip) => ip, | ||||
|         Err(e) => { | ||||
|             log::warn!("Failed to parse an IP address: {}", e); | ||||
|             return None; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     if let IpAddr::V6(ipv6) = &mut ip { | ||||
|         let mut octets = ipv6.octets(); | ||||
|         for o in octets.iter_mut().skip(8) { | ||||
|             *o = 0; | ||||
|         } | ||||
|         ip = IpAddr::V6(Ipv6Addr::from(octets)); | ||||
|     } | ||||
|  | ||||
|     Some(ip) | ||||
| } | ||||
|  | ||||
| /// Check if two ips matches | ||||
| pub fn match_ip(pattern: &str, ip: &str) -> bool { | ||||
|     if pattern.eq(ip) { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     if pattern.ends_with('*') && ip.starts_with(&pattern.replace('*', "")) { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     false | ||||
| } | ||||
|  | ||||
| /// Get the remote IP address | ||||
| pub fn get_remote_ip(req: &HttpRequest, proxy_ip: Option<&str>) -> IpAddr { | ||||
|     let mut ip = req.peer_addr().unwrap().ip(); | ||||
|  | ||||
|     // We check if the request comes from a trusted reverse proxy | ||||
|     if let Some(proxy) = proxy_ip.as_ref() { | ||||
|         if match_ip(proxy, &ip.to_string()) { | ||||
|             if let Some(header) = req.headers().get("X-Forwarded-For") { | ||||
|                 let header = header.to_str().unwrap(); | ||||
|  | ||||
|                 let remote_ip = if let Some((upstream_ip, _)) = header.split_once(',') { | ||||
|                     upstream_ip | ||||
|                 } else { | ||||
|                     header | ||||
|                 }; | ||||
|  | ||||
|                 if let Some(upstream_ip) = parse_ip(remote_ip) { | ||||
|                     ip = upstream_ip; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     ip | ||||
| } | ||||
|  | ||||
| #[derive(Copy, Clone, Debug, Eq, PartialEq)] | ||||
| pub struct RemoteIP(pub IpAddr); | ||||
|  | ||||
| impl From<RemoteIP> for IpAddr { | ||||
|     fn from(i: RemoteIP) -> Self { | ||||
|         i.0 | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl FromRequest for RemoteIP { | ||||
|     type Error = Error; | ||||
|     type Future = Ready<Result<Self, Error>>; | ||||
|  | ||||
|     #[inline] | ||||
|     fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { | ||||
|         ready(Ok(RemoteIP(get_remote_ip( | ||||
|             req, | ||||
|             AppConfig::get().proxy_ip.as_deref(), | ||||
|         )))) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(test)] | ||||
| mod test { | ||||
|     use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; | ||||
|     use std::str::FromStr; | ||||
|  | ||||
|     use crate::remote_ip::{get_remote_ip, parse_ip}; | ||||
|     use actix_web::test::TestRequest; | ||||
|  | ||||
|     #[test] | ||||
|     fn test_get_remote_ip() { | ||||
|         let req = TestRequest::default() | ||||
|             .peer_addr(SocketAddr::from_str("192.168.1.1:1000").unwrap()) | ||||
|             .to_http_request(); | ||||
|         assert_eq!( | ||||
|             get_remote_ip(&req, None), | ||||
|             "192.168.1.1".parse::<IpAddr>().unwrap() | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_get_remote_ip_from_proxy() { | ||||
|         let req = TestRequest::default() | ||||
|             .peer_addr(SocketAddr::from_str("192.168.1.1:1000").unwrap()) | ||||
|             .insert_header(("X-Forwarded-For", "1.1.1.1")) | ||||
|             .to_http_request(); | ||||
|         assert_eq!( | ||||
|             get_remote_ip(&req, Some("192.168.1.1")), | ||||
|             "1.1.1.1".parse::<IpAddr>().unwrap() | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_get_remote_ip_from_proxy_2() { | ||||
|         let req = TestRequest::default() | ||||
|             .peer_addr(SocketAddr::from_str("192.168.1.1:1000").unwrap()) | ||||
|             .insert_header(("X-Forwarded-For", "1.1.1.1, 1.2.2.2")) | ||||
|             .to_http_request(); | ||||
|         assert_eq!( | ||||
|             get_remote_ip(&req, Some("192.168.1.1")), | ||||
|             "1.1.1.1".parse::<IpAddr>().unwrap() | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_get_remote_ip_from_proxy_ipv6() { | ||||
|         let req = TestRequest::default() | ||||
|             .peer_addr(SocketAddr::from_str("192.168.1.1:1000").unwrap()) | ||||
|             .insert_header(("X-Forwarded-For", "10::1, 1.2.2.2")) | ||||
|             .to_http_request(); | ||||
|         assert_eq!( | ||||
|             get_remote_ip(&req, Some("192.168.1.1")), | ||||
|             "10::".parse::<IpAddr>().unwrap() | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_get_remote_ip_from_no_proxy() { | ||||
|         let req = TestRequest::default() | ||||
|             .peer_addr(SocketAddr::from_str("192.168.1.1:1000").unwrap()) | ||||
|             .insert_header(("X-Forwarded-For", "1.1.1.1, 1.2.2.2")) | ||||
|             .to_http_request(); | ||||
|         assert_eq!( | ||||
|             get_remote_ip(&req, None), | ||||
|             "192.168.1.1".parse::<IpAddr>().unwrap() | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_get_remote_ip_from_other_proxy() { | ||||
|         let req = TestRequest::default() | ||||
|             .peer_addr(SocketAddr::from_str("192.168.1.1:1000").unwrap()) | ||||
|             .insert_header(("X-Forwarded-For", "1.1.1.1, 1.2.2.2")) | ||||
|             .to_http_request(); | ||||
|         assert_eq!( | ||||
|             get_remote_ip(&req, Some("192.168.1.2")), | ||||
|             "192.168.1.1".parse::<IpAddr>().unwrap() | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn parse_bad_ip() { | ||||
|         let ip = parse_ip("badbad"); | ||||
|         assert_eq!(None, ip); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn parse_ip_v4_address() { | ||||
|         let ip = parse_ip("192.168.1.1").unwrap(); | ||||
|         assert_eq!(ip, IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1))); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn parse_ip_v6_address() { | ||||
|         let ip = parse_ip("2a00:1450:4007:813::200e").unwrap(); | ||||
|         assert_eq!( | ||||
|             ip, | ||||
|             IpAddr::V6(Ipv6Addr::new(0x2a00, 0x1450, 0x4007, 0x813, 0, 0, 0, 0)) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn parse_ip_v6_address_2() { | ||||
|         let ip = parse_ip("::1").unwrap(); | ||||
|         assert_eq!(ip, IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0))); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn parse_ip_v6_address_3() { | ||||
|         let ip = parse_ip("a::1").unwrap(); | ||||
|         assert_eq!(ip, IpAddr::V6(Ipv6Addr::new(0xa, 0, 0, 0, 0, 0, 0, 0))); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										40
									
								
								src/state_manager.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/state_manager.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| use crate::crypto_wrapper::CryptoWrapper; | ||||
| use crate::remote_ip::RemoteIP; | ||||
| use crate::time_utils::time; | ||||
| use crate::Res; | ||||
| use bincode::{Decode, Encode}; | ||||
| use std::net::IpAddr; | ||||
|  | ||||
| pub struct StateManager; | ||||
|  | ||||
| static mut WRAPPER: Option<CryptoWrapper> = None; | ||||
|  | ||||
| #[derive(Encode, Decode, Debug)] | ||||
| struct State { | ||||
|     ip: IpAddr, | ||||
|     expire: u64, | ||||
| } | ||||
|  | ||||
| impl State { | ||||
|     pub fn new(ip: IpAddr) -> Self { | ||||
|         Self { | ||||
|             ip, | ||||
|             expire: time() + 15 * 60, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl StateManager { | ||||
|     pub fn init() { | ||||
|         unsafe { | ||||
|             WRAPPER = Some(CryptoWrapper::new_random()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Generate a new state | ||||
|     pub fn gen_state(ip: &RemoteIP) -> Res<String> { | ||||
|         let state = State::new(ip.0); | ||||
|  | ||||
|         unsafe { WRAPPER.as_ref().unwrap() }.encrypt(&state) | ||||
|     } | ||||
| } | ||||
							
								
								
									
										9
									
								
								src/time_utils.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/time_utils.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| use std::time::{SystemTime, UNIX_EPOCH}; | ||||
|  | ||||
| /// Get current time since epoch | ||||
| pub fn time() -> u64 { | ||||
|     SystemTime::now() | ||||
|         .duration_since(UNIX_EPOCH) | ||||
|         .unwrap() | ||||
|         .as_secs() | ||||
| } | ||||
		Reference in New Issue
	
	Block a user