From 603d2bb46d38fa7d4c46df4cb9aad895916ec011 Mon Sep 17 00:00:00 2001 From: c0repwn3r Date: Wed, 19 Apr 2023 09:30:40 -0400 Subject: [PATCH] work on callback --- Cargo.lock | 276 ++++++++++++++++++++++++++++++++ api/Cargo.toml | 6 +- api/src/config.rs | 2 +- api/src/main.rs | 1 + api/src/routes/callback.rs | 65 +++++++- api/templates/select_realm.tera | 1 + 6 files changed, 348 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3a4f07de31998d0aa34e9fb7c221b7a0a7a4f0fc..e1eab354d8e5b54e6b86ec7ae8ee3826f07e7712 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -877,6 +877,16 @@ 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" @@ -1167,6 +1177,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" @@ -1462,6 +1487,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 = "http-range" version = "0.1.5" @@ -1486,6 +1522,43 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026" +[[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 = "iana-time-zone" version = "0.1.56" @@ -1567,6 +1640,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 = "itertools" version = "0.10.5" @@ -1600,6 +1679,22 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jwt" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6204285f77fe7d9784db3fdc449ecce1a0114927a51d5a41c4c7a292011c015f" +dependencies = [ + "base64 0.13.1", + "crypto-common", + "digest", + "hmac", + "openssl", + "serde", + "serde_json", + "sha2", +] + [[package]] name = "kv-log-macro" version = "1.0.7" @@ -1798,6 +1893,24 @@ dependencies = [ "syn 1.0.109", ] +[[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" @@ -1895,6 +2008,50 @@ version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +[[package]] +name = "openssl" +version = "0.10.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e30d8bc91859781f0a943411186324d580f2bbeb71b452fe91ae344806af3f1" +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.14", +] + +[[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.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d3d193fb1488ad46ffe3aaabc912cc931d02ee8518fe2959aea8ef52718b0c0" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "optional" version = "0.5.0" @@ -2429,6 +2586,43 @@ dependencies = [ "bytecheck", ] +[[package]] +name = "reqwest" +version = "0.11.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" +dependencies = [ + "base64 0.21.0", + "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 = "ring" version = "0.16.20" @@ -2573,6 +2767,15 @@ dependencies = [ "winapi-util", ] +[[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" @@ -2764,6 +2967,29 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[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" @@ -3099,8 +3325,11 @@ dependencies = [ "actix-files", "actix-request-identifier", "actix-web", + "jwt", "log", "once_cell", + "openssl", + "reqwest", "sea-orm", "serde", "simple_logger", @@ -3306,6 +3535,16 @@ dependencies = [ "windows-sys 0.45.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-rustls" version = "0.23.4" @@ -3385,6 +3624,12 @@ dependencies = [ "winnow", ] +[[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.37" @@ -3433,6 +3678,12 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + [[package]] name = "tungstenite" version = "0.19.0" @@ -3623,6 +3874,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "vec_map" version = "0.8.2" @@ -3651,6 +3908,16 @@ dependencies = [ "winapi-util", ] +[[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" @@ -3979,6 +4246,15 @@ dependencies = [ "memchr", ] +[[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" diff --git a/api/Cargo.toml b/api/Cargo.toml index 2d87f89ceb523e78f8c66e75077c0cb8bc875517..a2f6e761431c393e35a4d81fc296ae2f404f91e0 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -24,4 +24,8 @@ starkingdoms_api_entities = { version = "0.1.0", path = "starkingdoms_api_entiti ulid = "1.0.0" # Identifiers -tera = "1" # Templates \ No newline at end of file +tera = "1" # Templates + +jwt = { version = "0.16", features = ["openssl"] } # Auth +openssl = "0.10" # Auth +reqwest = "0.11" # Auth \ No newline at end of file diff --git a/api/src/config.rs b/api/src/config.rs index 1c79705b5ec2779f88b6a05d95a554e19c967fa9..1fce88287c1d26c38934b65814b153129aee777d 100644 --- a/api/src/config.rs +++ b/api/src/config.rs @@ -67,7 +67,7 @@ issuer = "https://api.e3t.cc" #[derive(Serialize, Deserialize, Debug, Clone)] pub struct StarkingdomsApiConfigRealm { pub authorize_url: String, - pub public_key_url: String, + pub public_key: String, pub issuer: String } diff --git a/api/src/main.rs b/api/src/main.rs index bb9a55737f0b44698d9d73ec6f204f6432890195..12f8d65d17c4835056268aa79cd614253c93ba6d 100644 --- a/api/src/main.rs +++ b/api/src/main.rs @@ -65,6 +65,7 @@ async fn main() -> Result<(), Box> { })) .wrap(RequestIdentifier::with_generator(|| HeaderValue::from_str(&ulid::Ulid::new().to_string()).unwrap())) .service(routes::select_realm::select_realm) + .service(routes::callback::callback) .service(actix_files::Files::new("/static", "static")) }).bind(CONFIG.server.bind)?.run().await?; diff --git a/api/src/routes/callback.rs b/api/src/routes/callback.rs index 731506fc043e52265360359e72c2aa9809a9e237..82e595972b5a20a32faae21c2da935e2e72bedca 100644 --- a/api/src/routes/callback.rs +++ b/api/src/routes/callback.rs @@ -1,14 +1,77 @@ +use std::collections::BTreeMap; use actix_web::{get, HttpResponse}; use actix_web::web::{Data, Query}; +use jwt::{PKeyWithDigest, VerifyWithKey}; +use log::{debug, error}; +use openssl::hash::MessageDigest; +use openssl::pkey::PKey; use serde::Deserialize; use crate::AppState; +use crate::config::CONFIG; +use crate::error::{APIError, APIErrorsResponse}; #[derive(Deserialize)] pub struct CallbackQueryParams { - + pub token: String, + pub realm: String } #[get("/callback")] pub async fn callback(query: Query, state: Data) -> HttpResponse { + // verify token from auth provider API + + // 1. load the public key + let realm = match CONFIG.realms.get(&query.realm) { + Some(r) => r, + None => { + error!("realm not found"); + return HttpResponse::Unauthorized().json(APIErrorsResponse { + errors: vec![ + APIError { + code: "ERR_UNKNOWN_REALM".to_string(), + message: "Unknown realm".to_string(), + path: None, + } + ], + }) + } + }; + + let rs256_pub_key = PKeyWithDigest { + digest: MessageDigest::sha256(), + key: PKey::public_key_from_pem(realm.public_key.as_bytes()).unwrap() + }; + + let token: BTreeMap = match query.token.verify_with_key(&rs256_pub_key) { + Ok(tkn) => tkn, + Err(e) => { + error!("[callback] token verify error: {}", e); + return generic_unauthorized(); + } + }; + + let realm = match token.get("realm").ok_or(generic_unauthorized()) { + Ok(r) => r, + Err(e) => return e + }; + let realm_local_id = match token.get("realm_native_id").ok_or(generic_unauthorized()) { + Ok(r) => r, + Err(e) => return e + }; + + debug!("got authenticated realm native authorization: authenticated as {}:{}", realm, realm_local_id); + HttpResponse::Ok().finish() +} + +fn generic_unauthorized() -> HttpResponse { + HttpResponse::Unauthorized().json(APIErrorsResponse { + errors: vec![ + APIError { + code: "ERR_INVALID_STATE".to_string(), + message: "Unknown/invalid login state".to_string(), + path: None, + } + ], + }) } \ No newline at end of file diff --git a/api/templates/select_realm.tera b/api/templates/select_realm.tera index e428d14eaa0f1afd0df4bbd1274e40969fadd77d..17d213b47006f61f9186404e0a4976a726e40454 100644 --- a/api/templates/select_realm.tera +++ b/api/templates/select_realm.tera @@ -7,4 +7,5 @@ {% for realm_id, realm in realms %} {{ realm_id }} {% endfor %} +

Selecting an authentication provider will redirect you to our trusted partner e3team's website for login. You will be returned to StarKingdoms when finished.

{% endblock body %} \ No newline at end of file