oidc: add debug/trace logs

This commit is contained in:
lafleur 2025-08-04 17:57:47 +02:00
commit 14f6d07b27
6 changed files with 26 additions and 14 deletions

View file

@ -22,7 +22,7 @@ pub(crate) async fn authorize(
Query(query): Query<AuthorizationQuery>, Query(query): Query<AuthorizationQuery>,
oauth: OidcRequest, oauth: OidcRequest,
) -> Result<OidcResponse> { ) -> Result<OidcResponse> {
tracing::trace!("processing OAuth request: {query:?}"); tracing::trace!("processing OAuth request: {query:#?}");
// Enforce MSC2964's restrictions on OAuth2 flow. // Enforce MSC2964's restrictions on OAuth2 flow.
let Ok(scope) = percent_decode_str(&query.scope).decode_utf8() else { let Ok(scope) = percent_decode_str(&query.scope).decode_utf8() else {
return Err(err!(Request(Unknown("the scope could not be percent-decoded")))); return Err(err!(Request(Unknown("the scope could not be percent-decoded"))));
@ -50,6 +50,10 @@ pub(crate) async fn authorize(
}, },
} }
// TODO register the device ID ? // TODO register the device ID ?
tracing::debug!(
"submitting OIDC authorisation for token : {:#?}",
oauth.authorization_header().unwrap()
);
services services
.oidc .oidc

View file

@ -19,6 +19,7 @@ pub(crate) async fn oidc_login(
let query: LoginQuery = request.clone().try_into().map_err(|LoginError(err)| { let query: LoginQuery = request.clone().try_into().map_err(|LoginError(err)| {
err!(Request(InvalidParam("Cannot process login form. {err}"))) err!(Request(InvalidParam("Cannot process login form. {err}")))
})?; })?;
tracing::trace!("processing login query {:#?}", query.clone());
// Only accept local usernames. Mostly to simplify things at first. // Only accept local usernames. Mostly to simplify things at first.
let user_id = let user_id =
UserId::parse_with_server_name(query.username.clone(), &services.config.server_name) UserId::parse_with_server_name(query.username.clone(), &services.config.server_name)
@ -35,10 +36,11 @@ pub(crate) async fn oidc_login(
if verify_password(&query.password, &valid_hash).is_err() { if verify_password(&query.password, &valid_hash).is_err() {
return Err(err!(Request(InvalidParam("password does not match")))); return Err(err!(Request(InvalidParam("password does not match"))));
} }
tracing::info!("logging in: {user_id:?}");
let hostname = services.config.server_name.host(); let hostname = services.config.server_name.host();
let authorization_query: AuthorizationQuery = query.into(); let authorization_query: AuthorizationQuery = query.into();
tracing::info!("logging in {user_id:?}");
tracing::debug!("login {user_id} authorisation query : {authorization_query:#?}");
services services
.oidc .oidc
@ -46,5 +48,5 @@ pub(crate) async fn oidc_login(
.with_solicitor(oidc_consent_form(hostname, &authorization_query)) .with_solicitor(oidc_consent_form(hostname, &authorization_query))
.authorization_flow() .authorization_flow()
.execute(request) .execute(request)
.map_err(|err| err!(Request(Unknown("authorization failed: {err:?}")))) .map_err(|err| err!(Request(Unknown("authorisation failed: {err:?}"))))
} }

View file

@ -5,7 +5,7 @@ use reqwest::Url;
use ruma::DeviceId; use ruma::DeviceId;
/// 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)] #[derive(serde::Deserialize, Clone, Debug)]
pub(crate) struct ClientQuery { pub(crate) struct ClientQuery {
/// Human-readable name. /// Human-readable name.
client_name: String, client_name: String,
@ -32,7 +32,7 @@ pub(crate) struct ClientQuery {
} }
/// A successful response that the client was registered. /// A successful response that the client was registered.
#[derive(serde::Serialize)] #[derive(serde::Serialize, Debug)]
pub(crate) struct ClientResponse { pub(crate) struct ClientResponse {
client_id: String, client_id: String,
client_name: String, client_name: String,
@ -58,6 +58,7 @@ pub(crate) async fn register_client(
State(services): State<crate::State>, State(services): State<crate::State>,
Json(client): Json<ClientQuery>, Json(client): Json<ClientQuery>,
) -> Result<Json<ClientResponse>> { ) -> Result<Json<ClientResponse>> {
tracing::trace!("processing OIDC device register request for client: {client:#?}");
let Some(redirect_uri) = client.redirect_uris.first().cloned() else { let Some(redirect_uri) = client.redirect_uris.first().cloned() else {
return Err(err!(Request(Unknown( return Err(err!(Request(Unknown(
"register request should contain at least a redirect_uri" "register request should contain at least a redirect_uri"
@ -77,8 +78,7 @@ pub(crate) async fn register_client(
.parse() .parse()
.expect("device ID should parse in Matrix scope"), .expect("device ID should parse in Matrix scope"),
))?; ))?;
let client_response = ClientResponse {
Ok(Json(ClientResponse {
client_id: device_id.to_string(), client_id: device_id.to_string(),
client_name: client.client_name.clone(), client_name: client.client_name.clone(),
client_uri: client.client_uri.clone(), client_uri: client.client_uri.clone(),
@ -90,5 +90,8 @@ pub(crate) async fn register_client(
response_types: client.response_types.clone(), response_types: client.response_types.clone(),
grant_types: client.grant_types.clone(), grant_types: client.grant_types.clone(),
application_type: client.application_type, application_type: client.application_type,
})) };
tracing::debug!("OIDC device registered : {client_response:#?}");
Ok(Json(client_response))
} }

View file

@ -11,6 +11,7 @@ pub(crate) async fn token(
State(services): State<crate::State>, State(services): State<crate::State>,
oauth: OidcRequest, oauth: OidcRequest,
) -> Result<OidcResponse> { ) -> Result<OidcResponse> {
tracing::trace!("processing OpenID token request {:#?}", oauth);
let Some(body) = oauth.body() else { let Some(body) = oauth.body() else {
return Err(err!(Request(Unknown("OAuth request had an empty body")))); return Err(err!(Request(Unknown("OAuth request had an empty body"))));
}; };
@ -18,6 +19,7 @@ pub(crate) async fn token(
.unique_value("grant_type") .unique_value("grant_type")
.map(|value| value.to_string()); .map(|value| value.to_string());
let endpoint = services.oidc.endpoint(); let endpoint = services.oidc.endpoint();
tracing::debug!("submitting OpenID token request for grant type {grant_type:?}");
match grant_type.as_deref() { match grant_type.as_deref() {
| Some("authorization_code") => endpoint | Some("authorization_code") => endpoint

View file

@ -1,3 +1,4 @@
use std::borrow::Cow;
use askama::Template; use askama::Template;
use axum::http::StatusCode; use axum::http::StatusCode;
use oxide_auth::frontends::simple::request::Body; use oxide_auth::frontends::simple::request::Body;
@ -28,8 +29,8 @@ pub fn oidc_consent_form(hostname: &str, query: &AuthorizationQuery) -> OidcResp
fn consent_page(hostname: &str, query: &AuthorizationQuery, route: &str, nonce: &str) -> String { fn consent_page(hostname: &str, query: &AuthorizationQuery, route: &str, nonce: &str) -> String {
let response_mode = &query.response_mode.clone() let response_mode = &query.response_mode.clone()
.unwrap_or_else(|| match query.redirect_uri.scheme() { .unwrap_or_else(|| match query.redirect_uri.scheme() {
| "https" => "fragment", | "https" => Cow::Borrowed("fragment"),
| _ => "query" | _ => Cow::Borrowed("query")
}); });
let template = ConsentPageTemplate { let template = ConsentPageTemplate {
nonce, nonce,
@ -42,7 +43,7 @@ fn consent_page(hostname: &str, query: &AuthorizationQuery, route: &str, nonce:
code_challenge: &encode(query.code_challenge.as_str()), code_challenge: &encode(query.code_challenge.as_str()),
code_challenge_method: &encode(query.code_challenge_method.as_str()), code_challenge_method: &encode(query.code_challenge_method.as_str()),
response_type: &encode(query.response_type.as_str()), response_type: &encode(query.response_type.as_str()),
response_mode: &encode(response_mode), response_mode: &encode(response_mode.as_str()),
}; };
template.render().expect("consent page render") template.render().expect("consent page render")

View file

@ -1,4 +1,4 @@
use std::str::FromStr; use std::{borrow::Cow, str::FromStr};
use askama::Template; use askama::Template;
use axum::http::StatusCode; use axum::http::StatusCode;
@ -65,8 +65,8 @@ impl TryFrom<OidcRequest> for LoginQuery {
// when over https. It's required by the spec but Fractal doesn't provide it. // when over https. It's required by the spec but Fractal doesn't provide it.
let response_mode = body.unique_value("response_mode") let response_mode = body.unique_value("response_mode")
.unwrap_or_else(|| match redirect_uri.scheme() { .unwrap_or_else(|| match redirect_uri.scheme() {
| "https" => "fragment", | "https" => Cow::Borrowed("fragment"),
| _ => "query" | _ => Cow::Borrowed("query")
}); });
Ok(Self { Ok(Self {