feat: Implement magic link authentication

This commit introduces a new magic link authentication flow.
The desktop client can now request a temporary, one-time-use token from
the server.
This token is then used to open a URL in the system browser, which
redirects to the server.
The server consumes the token, installs a regular web session, and
redirects the user
This commit is contained in:
2026-04-19 16:00:12 +02:00
parent 0d5c2f5888
commit 76e8ee18e9
13 changed files with 690 additions and 39 deletions
+27 -8
View File
@@ -283,14 +283,33 @@ impl DoctateApp {
let Some(cfg) = &self.config else {
return;
};
let url = format!(
"{}/web/cases/{}",
cfg.server_url.trim_end_matches('/'),
case_id
);
if let Err(e) = webbrowser::open(&url) {
warn!(url = %url, error = %e, "open browser failed");
}
let server_url = cfg.server_url.trim_end_matches('/').to_owned();
let api_key = cfg.api_key.clone();
let http = self.http_client.clone();
let return_to = format!("/web/cases/{case_id}");
let fallback_url = format!("{server_url}{return_to}");
// Fire-and-forget on the runtime. Blocking the egui UI thread on
// an HTTP round-trip would freeze the window for ~100500ms.
self.runtime.spawn(async move {
let url = match crate::magic_link::build_magic_url(
&http,
&server_url,
&api_key,
&return_to,
)
.await
{
Ok(u) => u,
Err(e) => {
warn!(error = %e, "magic-link request failed; falling back to plain URL");
fallback_url
}
};
if let Err(e) = webbrowser::open(&url) {
warn!(url = %url, error = %e, "open browser failed");
}
});
}
fn drain_recorder_events(&mut self) {