mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2025-09-10 15:52:48 +02:00
fix oxide-auth's redirect_uri comparison
oxide-auth's `RegisteredUrl::IgnorePortOnLocalhost` doesn't work when the host is 127.0.0.1 or [::1]. This commit lets the authentication process translate the host. The new registrar already supports this.
This commit is contained in:
parent
6d9aee4d9f
commit
2784eec60a
2 changed files with 27 additions and 15 deletions
|
@ -3,6 +3,7 @@ use conduwuit::{Result, err};
|
|||
use oxide_auth::primitives::prelude::Client;
|
||||
use reqwest::Url;
|
||||
use ruma::{DeviceId, identifiers_validation};
|
||||
use conduwuit_service::oidc::registrar::normalize_redirect;
|
||||
|
||||
/// The required parameters to register a new client for OAuth2 application.
|
||||
#[derive(serde::Deserialize, Clone, Debug)]
|
||||
|
@ -61,11 +62,18 @@ pub(crate) async fn register_client(
|
|||
Json(client): Json<ClientQuery>,
|
||||
) -> Result<Json<ClientResponse>> {
|
||||
tracing::trace!("processing OIDC device register request for client: {client:#?}");
|
||||
let Some(redirect_uri) = client.redirect_uris.first().cloned() else {
|
||||
return Err(err!(Request(Unknown(
|
||||
"register request should contain at least a redirect_uri"
|
||||
))));
|
||||
};
|
||||
if client.redirect_uris.len() == 0 {
|
||||
return Err(err!(Request(Unknown(
|
||||
"the client's registration request should contain at least a redirect_uri"
|
||||
))));
|
||||
}
|
||||
let mut redirect_uris = client.redirect_uris.clone();
|
||||
let redirect_uri = redirect_uris.pop().expect("at least one redirect_uri");
|
||||
let redirect_uri = normalize_redirect(redirect_uri);
|
||||
let remaining_uris = redirect_uris
|
||||
.into_iter()
|
||||
.map(|url| normalize_redirect(url))
|
||||
.collect();
|
||||
let device_id = DeviceId::new();
|
||||
let scope = format!(
|
||||
"urn:matrix:org.matrix.msc2967.client:api:* \
|
||||
|
|
|
@ -20,8 +20,9 @@ pub fn normalize_redirect_hostname(url: Url) -> Url {
|
|||
new_url
|
||||
}
|
||||
|
||||
/// The redirect_uri has to be wrapped in an IgnorePortOnLocalhost for oxide-auth
|
||||
/// to ignore the port when comparing it with the registered ones.
|
||||
/// If `url` is a localhost (either 'localhost', '127.0.0.1' or '[::1]'), wrap it in an
|
||||
/// IgnorePortOnLocalhost, so that oxide-auth ignores the port when comparing it with the
|
||||
/// registered ones.
|
||||
pub fn normalize_redirect(url: Url) -> RegisteredUrl {
|
||||
let new_url = normalize_redirect_hostname(url);
|
||||
|
||||
|
@ -105,11 +106,13 @@ impl Registrar for ClientMap {
|
|||
Some(stored) => stored,
|
||||
};
|
||||
|
||||
// Perform exact matching as motivated in the rfc, just substitute "127.0.0.1" and
|
||||
// "[::1]" for "localhost".
|
||||
let redirect_uri = bound.redirect_uri
|
||||
// Perform exact matching as motivated in the rfc, but substitute "127.0.0.1" and
|
||||
// "[::1]" for "localhost" to let oxide-auth ignore their port.
|
||||
let redirect_uri = bound.redirect_uri;
|
||||
let normalized_uri = redirect_uri
|
||||
.clone()
|
||||
.map(|u| normalize_redirect(u.to_url()));
|
||||
let registered_url = match redirect_uri {
|
||||
let registered_url = match normalized_uri {
|
||||
None => client.redirect_uri.clone(),
|
||||
Some(url) => {
|
||||
let original = std::iter::once(&client.redirect_uri);
|
||||
|
@ -118,7 +121,8 @@ impl Registrar for ClientMap {
|
|||
.chain(alternatives)
|
||||
.any(|registered| *registered == url)
|
||||
{
|
||||
url.clone().into()
|
||||
// If normalized_uri is Some(url), so is redirect_uri, so unwrap().
|
||||
redirect_uri.unwrap().into_owned().into()
|
||||
} else {
|
||||
tracing::debug!("the request's redirect url didn't match any registered. bound: {:?}, in client {:#?}", url, client);
|
||||
return Err(RegistrarError::Unspecified);
|
||||
|
@ -153,9 +157,9 @@ impl Registrar for ClientMap {
|
|||
.ok_or_else(|| {
|
||||
tracing::debug!("this client is not registered yet: {client_id:?}.");
|
||||
RegistrarError::Unspecified
|
||||
}).and_then(|client| {
|
||||
RegisteredClient::new(client, password_policy).check_authentication(passphrase)
|
||||
})?;
|
||||
}).and_then(|client|
|
||||
RegisteredClient::new(client, password_policy).check_authentication(passphrase)
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue