diff --git a/Cargo.lock b/Cargo.lock index 86266bc3a..ea31aed3c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3958,12 +3958,12 @@ version = "0.0.1-pre.6" dependencies = [ "enum_dispatch", "http 1.1.0", - "http-compat", "kitsune-config", "kitsune-error", "kitsune-http-client", "moka", "multiplex-pool", + "oauth2", "once_cell", "openidconnect", "redis", @@ -5087,14 +5087,14 @@ dependencies = [ [[package]] name = "oauth2" -version = "4.4.2" +version = "5.0.0-alpha.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c38841cdd844847e3e7c8d29cef9dcfed8877f8f56f9071f77843ecf3baf937f" +checksum = "098af5a5110b4deacf3200682963713b143ae9d28762b739bdb7b98429dfaf68" dependencies = [ - "base64 0.13.1", + "base64 0.22.0", "chrono", "getrandom 0.2.14", - "http 0.2.12", + "http 1.1.0", "rand 0.8.5", "serde", "serde_json", @@ -5141,16 +5141,16 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "openidconnect" -version = "3.5.0" +version = "4.0.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47e80a9cfae4462dd29c41e987edd228971d6565553fbc14b8a11e666d91590" +checksum = "6b38a873646c7f83bb723774220f68385bf39e10faafc2e2e51894882d9a5a0f" dependencies = [ - "base64 0.13.1", + "base64 0.21.7", "chrono", "dyn-clone", "ed25519-dalek", "hmac", - "http 0.2.12", + "http 1.1.0", "itertools 0.10.5", "log", "oauth2", @@ -5160,7 +5160,6 @@ dependencies = [ "rsa", "serde", "serde-value", - "serde_derive", "serde_json", "serde_path_to_error", "serde_plain", diff --git a/crates/kitsune-oidc/Cargo.toml b/crates/kitsune-oidc/Cargo.toml index 3e82d4413..0804c4347 100644 --- a/crates/kitsune-oidc/Cargo.toml +++ b/crates/kitsune-oidc/Cargo.toml @@ -8,14 +8,14 @@ license.workspace = true [dependencies] enum_dispatch = "0.3.13" http = "1.1.0" -http-compat = { path = "../../lib/http-compat" } kitsune-config = { path = "../kitsune-config" } kitsune-error = { path = "../kitsune-error" } kitsune-http-client = { path = "../kitsune-http-client" } moka = { version = "0.12.7", features = ["future"] } multiplex-pool = { path = "../../lib/multiplex-pool" } +oauth2 = { version = "5.0.0-alpha.4", default-features = false } once_cell = "1.19.0" -openidconnect = { version = "3.5.0", default-features = false, features = [ +openidconnect = { version = "4.0.0-alpha.1", default-features = false, features = [ # Accept these two, per specification invalid, cases to increase compatibility "accept-rfc3339-timestamps", "accept-string-booleans", diff --git a/crates/kitsune-oidc/src/http.rs b/crates/kitsune-oidc/src/http.rs index 81d1f1916..4a8cf9855 100644 --- a/crates/kitsune-oidc/src/http.rs +++ b/crates/kitsune-oidc/src/http.rs @@ -1,5 +1,3 @@ -use http::Request; -use http_compat::Compat; use kitsune_http_client::Client as HttpClient; use once_cell::sync::Lazy; use openidconnect::{HttpRequest, HttpResponse}; @@ -7,16 +5,12 @@ use openidconnect::{HttpRequest, HttpResponse}; static HTTP_CLIENT: Lazy = Lazy::new(HttpClient::default); pub async fn async_client(req: HttpRequest) -> Result { - let mut request = Request::builder() - .method(req.method.compat()) - .uri(req.url.as_str()); - *request.headers_mut().unwrap() = req.headers.compat(); - let request = request.body(req.body.into()).unwrap(); - let response = HTTP_CLIENT.execute(request).await?; + let response = HTTP_CLIENT.execute(req.map(Into::into)).await?; - Ok(HttpResponse { - status_code: response.status().compat(), - headers: response.headers().clone().compat(), - body: response.bytes().await?.to_vec(), - }) + let mut builder = http::Response::builder() + .status(response.status()) + .version(response.version()); + *builder.headers_mut().unwrap() = response.headers().clone(); + + Ok(builder.body(response.bytes().await?.to_vec()).unwrap()) } diff --git a/crates/kitsune-oidc/src/lib.rs b/crates/kitsune-oidc/src/lib.rs index 77b6922ed..b7cb5af93 100644 --- a/crates/kitsune-oidc/src/lib.rs +++ b/crates/kitsune-oidc/src/lib.rs @@ -13,6 +13,38 @@ use openidconnect::{ use speedy_uuid::Uuid; use url::Url; +type OidcClient = openidconnect::Client< + openidconnect::EmptyAdditionalClaims, + openidconnect::core::CoreAuthDisplay, + openidconnect::core::CoreGenderClaim, + openidconnect::core::CoreJweContentEncryptionAlgorithm, + openidconnect::core::CoreJsonWebKey, + openidconnect::core::CoreAuthPrompt, + openidconnect::StandardErrorResponse, + openidconnect::StandardTokenResponse< + openidconnect::IdTokenFields< + openidconnect::EmptyAdditionalClaims, + openidconnect::EmptyExtraTokenFields, + openidconnect::core::CoreGenderClaim, + openidconnect::core::CoreJweContentEncryptionAlgorithm, + openidconnect::core::CoreJwsSigningAlgorithm, + >, + oauth2::basic::BasicTokenType, + >, + openidconnect::StandardTokenIntrospectionResponse< + openidconnect::EmptyExtraTokenFields, + oauth2::basic::BasicTokenType, + >, + oauth2::StandardRevocableToken, + openidconnect::StandardErrorResponse, + openidconnect::EndpointSet, + openidconnect::EndpointNotSet, + openidconnect::EndpointNotSet, + openidconnect::EndpointNotSet, + openidconnect::EndpointMaybeSet, + openidconnect::EndpointMaybeSet, +>; + mod state; pub mod http; @@ -36,7 +68,7 @@ pub struct UserInfo { #[derive(Clone)] pub struct OidcService { - client: CoreClient, + client: OidcClient, login_state_store: self::state::AnyStore, } @@ -45,7 +77,7 @@ impl OidcService { pub async fn initialise(config: &Configuration, redirect_uri: String) -> Result { let provider_metadata = CoreProviderMetadata::discover_async( IssuerUrl::new(config.server_url.to_string())?, - self::http::async_client, + &self::http::async_client, ) .await?; @@ -125,20 +157,22 @@ impl OidcService { let token_response = self .client - .exchange_code(AuthorizationCode::new(authorization_code)) + .exchange_code(AuthorizationCode::new(authorization_code))? .set_pkce_verifier(pkce_verifier) - .request_async(self::http::async_client) + .request_async(&self::http::async_client) .await?; let id_token = token_response .id_token() .ok_or_else(|| kitsune_error!("missing id token"))?; + let id_token_verifier = self.client.id_token_verifier(); let claims = id_token.claims(&self.client.id_token_verifier(), &nonce)?; if let Some(expected_hash) = claims.access_token_hash() { let actual_hash = AccessTokenHash::from_token( token_response.access_token(), - &id_token.signing_alg()?, + id_token.signing_alg()?, + id_token.signing_key(&id_token_verifier)?, )?; if actual_hash != *expected_hash {