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